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:
parent
8f4d087d08
commit
022c0c57d1
|
@ -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");
|
||||||
|
|
|
@ -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);
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 + "]";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue