fix for topics

git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/user/top-topics@130798 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Costantino Perciante 2016-07-25 18:55:32 +00:00
parent 8f4d087d08
commit 022c0c57d1
5 changed files with 93 additions and 278 deletions

View File

@ -21,7 +21,6 @@ import org.gcube.portal.databook.server.DBCassandraAstyanaxImpl;
import org.gcube.portal.databook.server.DatabookStore; import org.gcube.portal.databook.server.DatabookStore;
import org.gcube.portal.databook.shared.Feed; import org.gcube.portal.databook.shared.Feed;
import org.gcube.portlets.user.topics.client.TopicService; import org.gcube.portlets.user.topics.client.TopicService;
import org.gcube.portlets.user.topics.server.cache.TopicsCacheImpl;
import org.gcube.portlets.user.topics.shared.HashTagAndOccurrence; import org.gcube.portlets.user.topics.shared.HashTagAndOccurrence;
import org.gcube.portlets.user.topics.shared.HashtagsWrapper; import org.gcube.portlets.user.topics.shared.HashtagsWrapper;
import org.gcube.vomanagement.usermanagement.GroupManager; import org.gcube.vomanagement.usermanagement.GroupManager;
@ -49,6 +48,7 @@ public class TopicServiceImpl extends RemoteServiceServlet implements TopicServi
* The Cassandra store interface * The Cassandra store interface
*/ */
private DatabookStore store; private DatabookStore store;
/** /**
* connect to cassandra at startup * connect to cassandra at startup
*/ */
@ -56,6 +56,9 @@ public class TopicServiceImpl extends RemoteServiceServlet implements TopicServi
store = new DBCassandraAstyanaxImpl(); store = new DBCassandraAstyanaxImpl();
} }
/**
* close connection to cassandra at shutdown
*/
public void destroy() { public void destroy() {
store.closeConnection(); store.closeConnection();
} }
@ -88,7 +91,7 @@ public class TopicServiceImpl extends RemoteServiceServlet implements TopicServi
*/ */
@Override @Override
public HashtagsWrapper getHashtags() { public HashtagsWrapper getHashtags() {
ArrayList<String> hashtagsChart; ArrayList<String> hashtagsChart = new ArrayList<String>();
ASLSession session = getASLSession(); ASLSession session = getASLSession();
String userName = session.getUsername(); String userName = session.getUsername();
@ -97,138 +100,119 @@ public class TopicServiceImpl extends RemoteServiceServlet implements TopicServi
long timestampStart = System.currentTimeMillis(); long timestampStart = System.currentTimeMillis();
// get cache reference // get the reference time
TopicsCacheImpl topicsCache = TopicsCacheImpl.getCacheInstance(); Calendar referenceTime = Calendar.getInstance();
int currentMonth = referenceTime.get(Calendar.MONTH); // jan = 0, ..... dec = 11
referenceTime.set(Calendar.MONTH, currentMonth - WINDOW_SIZE_IN_MONTHS); // the year is automatically decreased if needed
hashtagsChart = topicsCache.get(currentScope); // print it
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
_log.debug("Reference time for trending topics is " + format.format(referenceTime.getTime()));
if(hashtagsChart != null){ try {
_log.debug("TopTopics for scope " + currentScope + " retrieved from the cache");
}
else{
_log.debug("TopTopics for scope " + currentScope + " are not in the cache, evaluating them...");
// create array
hashtagsChart = new ArrayList<String>();
// get the reference time
Calendar referenceTime = Calendar.getInstance();
int currentMonth = referenceTime.get(Calendar.MONTH); // jan = 0, ..... dec = 11
referenceTime.set(Calendar.MONTH, currentMonth - WINDOW_SIZE_IN_MONTHS); // the year is automatically decreased if needed
// print it //in case the portal is restarted and you have the social home open it will get test.user (no callback to set session info)
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); //this check just return nothing if that happens
_log.debug("Reference time for trending topics is " + format.format(referenceTime.getTime())); if (userName.compareTo("test.user") == 0) {
_log.debug("Found " + userName + " returning nothing");
return null;
}
try { ArrayList<HashTagAndOccurrence> toSort = new ArrayList<HashTagAndOccurrence>();
//in case the portal is restarted and you have the social home open it will get test.user (no callback to set session info) if (isInfrastructure) {
//this check just return nothing if that happens _log.debug("****** retrieving hashtags for user VREs");
if (userName.compareTo("test.user") == 0) {
_log.debug("Found " + userName + " returning nothing");
return null;
}
ArrayList<HashTagAndOccurrence> toSort = new ArrayList<HashTagAndOccurrence>();
if (isInfrastructure) {
_log.debug("****** retrieving hashtags for user VREs");
// different vres could have a same hashtag, we need to merge them // different vres could have a same hashtag, we need to merge them
Map<String, Integer> hashtags = new HashMap<String, Integer>(); Map<String, Integer> hashtags = new HashMap<String, Integer>();
// we need a map for the couple <hashtag, vre in which it is present> // we need a map for the couple <hashtag, vre in which it is present>
// it is needed because later we need to retrieve the most recent feed among the ones // it is needed because later we need to retrieve the most recent feed among the ones
// containing the hashtag itself // containing the hashtag itself
Map<String, List<String>> hashtagsInVres = new HashMap<String, List<String>>(); Map<String, List<String>> hashtagsInVres = new HashMap<String, List<String>>();
GroupManager gm = new LiferayGroupManager(); GroupManager gm = new LiferayGroupManager();
UserManager um = new LiferayUserManager(); UserManager um = new LiferayUserManager();
GCubeUser user = um.getUserByUsername(userName); GCubeUser user = um.getUserByUsername(userName);
List<GCubeGroup> groups = gm.listGroupsByUser(user.getUserId()); List<GCubeGroup> groups = gm.listGroupsByUser(user.getUserId());
for (GCubeGroup group : groups) { for (GCubeGroup group : groups) {
if (gm.isVRE(group.getGroupId())) { if (gm.isVRE(group.getGroupId())) {
String vreid = gm.getInfrastructureScope(group.getGroupId()); //get the scope String vreid = gm.getInfrastructureScope(group.getGroupId()); //get the scope
Map<String, Integer> map = store.getVREHashtagsWithOccurrenceFilteredByTime(vreid, referenceTime.getTimeInMillis()); Map<String, Integer> map = store.getVREHashtagsWithOccurrenceFilteredByTime(vreid, referenceTime.getTimeInMillis());
// merge the values if needed // merge the values if needed
for (String hashtag : map.keySet()) { for (String hashtag : map.keySet()) {
if(hashtags.containsKey(hashtag)){ if(hashtags.containsKey(hashtag)){
int currentValue = hashtags.get(hashtag); int currentValue = hashtags.get(hashtag);
int newValue = currentValue + map.get(hashtag); int newValue = currentValue + map.get(hashtag);
// remove and re-add // remove and re-add
hashtags.remove(hashtag); hashtags.remove(hashtag);
hashtags.put(hashtag, newValue); hashtags.put(hashtag, newValue);
// get the current list of vres in which the hashtag is present and add this new one // get the current list of vres in which the hashtag is present and add this new one
List<String> vres = hashtagsInVres.get(hashtag); List<String> vres = hashtagsInVres.get(hashtag);
vres.add(vreid); vres.add(vreid);
hashtagsInVres.remove(hashtag); hashtagsInVres.remove(hashtag);
hashtagsInVres.put(hashtag, vres); hashtagsInVres.put(hashtag, vres);
}else{ }else{
hashtags.put(hashtag, map.get(hashtag)); hashtags.put(hashtag, map.get(hashtag));
// put in the hashmap hashtagsInVres too // put in the hashmap hashtagsInVres too
List<String> vres = new ArrayList<String>(); List<String> vres = new ArrayList<String>();
vres.add(vreid); vres.add(vreid);
hashtagsInVres.put(hashtag, vres); hashtagsInVres.put(hashtag, vres);
}
} }
} }
} }
// now we need to evaluate score for each element
Map<String, Double> weights = evaluateWeight(hashtags, WINDOW_SIZE_IN_MONTHS, currentMonth, referenceTime, null, hashtagsInVres);
// at the end build the list
for (String hashtag : hashtags.keySet()) {
toSort.add(new HashTagAndOccurrence(hashtag, hashtags.get(hashtag), weights.get(hashtag)));
}
} }
// now we need to evaluate score for each element
Map<String, Double> weights = evaluateWeight(hashtags, WINDOW_SIZE_IN_MONTHS, currentMonth, referenceTime, null, hashtagsInVres);
// at the end build the list
for (String hashtag : hashtags.keySet()) {
toSort.add(new HashTagAndOccurrence(hashtag, hashtags.get(hashtag), weights.get(hashtag)));
}
}
else {
//else must be in a VRE scope //else must be in a VRE scope
else { String scope = session.getScope();
String scope = session.getScope(); _log.debug("****** retrieving hashtags for scope " + scope);
_log.debug("****** retrieving hashtags for scope " + scope); Map<String, Integer> hashtags = store.getVREHashtagsWithOccurrenceFilteredByTime(scope, referenceTime.getTimeInMillis());
Map<String, Integer> hashtags = store.getVREHashtagsWithOccurrenceFilteredByTime(scope, referenceTime.getTimeInMillis()); // now we need to evaluate the weight for each element
// now we need to evaluate the wiehgt for each element Map<String, Double> weights = evaluateWeight(hashtags, WINDOW_SIZE_IN_MONTHS, currentMonth, referenceTime, scope, null);
Map<String, Double> weights = evaluateWeight(hashtags, WINDOW_SIZE_IN_MONTHS, currentMonth, referenceTime, scope, null); for (String hashtag : hashtags.keySet()) {
for (String hashtag : hashtags.keySet()) { toSort.add(new HashTagAndOccurrence(hashtag, hashtags.get(hashtag), weights.get(hashtag)));
toSort.add(new HashTagAndOccurrence(hashtag, hashtags.get(hashtag), weights.get(hashtag)));
}
} }
_log.debug("Number of topics retrieved is " + toSort.size());
Collections.sort(toSort); // sort for weight
for (HashTagAndOccurrence wrapper : toSort) {
_log.debug("Entry is " + wrapper.toString() + " with weight " + wrapper.getWeight());
String hashtag = wrapper.getHashtag();
String href="\"?"+
new String(Base64.encodeBase64(GCubeSocialNetworking.HASHTAG_OID.getBytes()))+"="+
new String(Base64.encodeBase64(hashtag.getBytes()))+"\"";
String hashtagLink = "<a class=\"topiclink\" href=" + href + ">"+hashtag+"</a>";
hashtagsChart.add(hashtagLink);
}
// update the cache
topicsCache.insert(currentScope, hashtagsChart);
} }
catch (Exception e) {
e.printStackTrace(); _log.debug("Number of topics retrieved is " + toSort.size());
return null;
Collections.sort(toSort); // sort for weight
for (HashTagAndOccurrence wrapper : toSort) {
_log.debug("Entry is " + wrapper.toString() + " with weight " + wrapper.getWeight());
String hashtag = wrapper.getHashtag();
String href="\"?"+
new String(Base64.encodeBase64(GCubeSocialNetworking.HASHTAG_OID.getBytes()))+"="+
new String(Base64.encodeBase64(hashtag.getBytes()))+"\"";
String hashtagLink = "<a class=\"topiclink\" href=" + href + ">"+hashtag+"</a>";
hashtagsChart.add(hashtagLink);
} }
} }
catch (Exception e) {
e.printStackTrace();
return null;
}
long timestampEnd = System.currentTimeMillis() - timestampStart; long timestampEnd = System.currentTimeMillis() - timestampStart;
_log.debug("Overall time to retrieve hastags is " + timestampEnd + "ms"); _log.debug("Overall time to retrieve hastags is " + timestampEnd + "ms");

View File

@ -1,26 +0,0 @@
package org.gcube.portlets.user.topics.server.cache;
/**
* Cache interface
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @param <K> the key type
* @param <V> the value type
*/
public interface CacheInterface <K,V>{
/**
* Retrieve a value V from the cache
* @param key
* @return
*/
public V get(K key);
/**
* Insert an object V with key K into the cache
* @param key
* @param value
* @return
*/
public boolean insert(K key, V value);
}

View File

@ -1,26 +0,0 @@
package org.gcube.portlets.user.topics.server.cache;
/**
* Utility functions for caches
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*
*/
public class CacheUtilities {
/**
* Check if the bean expired
* @param beanTimestamp
* @param ttl
* @return <true> if expired, <false> otherwise
*/
public static boolean expired(long beanTimestamp, long ttl){
long currentTime = System.currentTimeMillis();
if((beanTimestamp + ttl) <= currentTime)
return true;
else
return false;
}
}

View File

@ -1,40 +0,0 @@
package org.gcube.portlets.user.topics.server.cache;
/**
* A bean object to be used as value within caches. It contains a TTL value too.
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*
* @param <V> the value type
*/
public class CacheValueBean <V>{
private V value;
private long TTL;
/**
* @param value
* @param tTL
*/
public CacheValueBean(V value, long ttl) {
super();
this.value = value;
this.TTL = ttl;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
public long getTTL() {
return TTL;
}
public void setTTL(long ttl) {
this.TTL = ttl;
}
@Override
public String toString() {
return "CacheValueBean [value=" + value + ", TTL=" + TTL + "]";
}
}

View File

@ -1,77 +0,0 @@
package org.gcube.portlets.user.topics.server.cache;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.LoggerFactory;
/**
* TopTopics cache: the key of each value is the scope
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*/
public class TopicsCacheImpl implements CacheInterface<String, ArrayList<String>> {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TopicsCacheImpl.class);
private static TopicsCacheImpl instance = new TopicsCacheImpl();
/**
* The hashmap
*/
private Map<String, CacheValueBean<ArrayList<String>>> cacheMap;
/**
* Cache entry expires after EXPIRED_AFTER ms
*/
private static final long EXPIRED_AFTER = 1000 * 60 * 2;
/**
* private constructor
*/
private TopicsCacheImpl(){
this.cacheMap = new HashMap<String, CacheValueBean<ArrayList<String>>>();
}
/**
* Retrieve the current cache instance object
* @return
*/
public static TopicsCacheImpl getCacheInstance(){
return instance;
}
@Override
public ArrayList<String> get(String key) {
if(cacheMap.containsKey(key)){
CacheValueBean<ArrayList<String>> bean = cacheMap.get(key);
if(CacheUtilities.expired(bean.getTTL(), EXPIRED_AFTER)){
cacheMap.remove(key);
logger.debug("TopTopics for scope " + key + "expired, return null");
}
else
return bean.getValue();
}
return null;
}
@Override
public boolean insert(String key, ArrayList<String> value) {
CacheValueBean<ArrayList<String>> newBean = new CacheValueBean<ArrayList<String>>(value, System.currentTimeMillis());
if(cacheMap.containsKey(key))
cacheMap.remove(key);
cacheMap.put(key, newBean);
return true;
}
}