diff --git a/src/main/java/org/gcube/portlet/user/userstatisticsportlet/client/StatisticsPanel.java b/src/main/java/org/gcube/portlet/user/userstatisticsportlet/client/StatisticsPanel.java index 551cbd8..98031a9 100644 --- a/src/main/java/org/gcube/portlet/user/userstatisticsportlet/client/StatisticsPanel.java +++ b/src/main/java/org/gcube/portlet/user/userstatisticsportlet/client/StatisticsPanel.java @@ -70,7 +70,7 @@ public class StatisticsPanel extends Composite { * Labels */ private final static String POSTS_LABEL = "Posts"; - private final static String STORAGE_LABEL = "Total Space Used"; + private final static String STORAGE_LABEL = "Space Used"; private final static String LIKES_COMMENTS_LABEL = "Got"; private final static String PROFILE_STRENGTH_LABEL = "Profile Strength"; diff --git a/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/UserStatisticsServiceImpl.java b/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/UserStatisticsServiceImpl.java index 70a79fe..d056ff8 100644 --- a/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/UserStatisticsServiceImpl.java +++ b/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/UserStatisticsServiceImpl.java @@ -16,6 +16,7 @@ import org.gcube.portal.databook.server.DBCassandraAstyanaxImpl; import org.gcube.portal.databook.server.DatabookStore; import org.gcube.portal.databook.shared.Feed; import org.gcube.portlet.user.userstatisticsportlet.client.UserStatisticsService; +import org.gcube.portlet.user.userstatisticsportlet.server.cache.UserInfrastructureSpaceCache; import org.gcube.portlet.user.userstatisticsportlet.shared.PostsStatsBean; import org.gcube.portlet.user.userstatisticsportlet.shared.UserInformation; import org.gcube.vomanagement.usermanagement.GroupManager; @@ -65,7 +66,7 @@ public class UserStatisticsServiceImpl extends RemoteServiceServlet implements U // get connection to Cassandra _log.debug("Getting connection to Cassandra.."); store = new DBCassandraAstyanaxImpl(); - + // add statistics option for profile pages and set to true createUserCustomField(CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY, true); @@ -176,9 +177,25 @@ public class UserStatisticsServiceImpl extends RemoteServiceServlet implements U long init = System.currentTimeMillis(); - Workspace workspace = HomeLibrary.getUserWorkspace(statisticsOfUsername); - long storage = workspace.getDiskUsage(); - storageInUse = formatFileSize(storage); + // retrieve the cache + UserInfrastructureSpaceCache cacheWorkspace = UserInfrastructureSpaceCache.getCacheInstance(); + + // check if information is present + Long storageInUseLong = (Long) cacheWorkspace.get(statisticsOfUsername); + + // if not, ask the workspace + if(storageInUseLong == null){ + + _log.debug("Information not available in the cache, asking workspace"); + Workspace workspace = HomeLibrary.getUserWorkspace(statisticsOfUsername); + storageInUseLong = workspace.getDiskUsage(); + + _log.debug("Put information in the cache"); + cacheWorkspace.insert(statisticsOfUsername, storageInUseLong); + + } + + storageInUse = formatFileSize(storageInUseLong); long end = System.currentTimeMillis(); _log.debug("[USER-STATISTICS] time taken to retrieve user space is " + (end - init) + "ms"); @@ -222,11 +239,11 @@ public class UserStatisticsServiceImpl extends RemoteServiceServlet implements U try{ + long init = System.currentTimeMillis(); + // check if the avatar is present boolean avatarPresent = (new LiferayUserManager().getUserAvatarBytes(statisticsOfUsername) != null); - long init = System.currentTimeMillis(); - User user = UserLocalServiceUtil.getUserByScreenName(SiteManagerUtil.getCompany().getCompanyId(), statisticsOfUsername); profileStrenght = evaluateProfileStrenght(user, avatarPresent); @@ -235,7 +252,7 @@ public class UserStatisticsServiceImpl extends RemoteServiceServlet implements U }catch(Exception e){ - _log.error("Profile strenght evaluation failed!!"); + _log.error("Profile strenght evaluation failed!!" + e.toString(), e); } } @@ -309,7 +326,7 @@ public class UserStatisticsServiceImpl extends RemoteServiceServlet implements U actualVre = temp[temp.length - 1]; } - + // page landing String pageLanding = PortalContext.getConfiguration().getSiteLandingPagePath(getThreadLocalRequest()); @@ -459,14 +476,14 @@ public class UserStatisticsServiceImpl extends RemoteServiceServlet implements U user.getExpandoBridge().setAttribute(CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY, show); } - + }catch(Exception e){ _log.error("Unable to check user's privacy for his statistics", e); } } } - + /** * On servlet instanciation, create the custom field and set it to startingValue * @param customFieldNameUserStatisticsVisibility @@ -474,31 +491,31 @@ public class UserStatisticsServiceImpl extends RemoteServiceServlet implements U */ private void createUserCustomField( String customFieldNameUserStatisticsVisibility, boolean startingValue) { - + // set permission checker setPermissionChecker(); - + try{ - + User defaultUser = UserLocalServiceUtil.getDefaultUser(ManagementUtils.getCompany().getCompanyId()); - + // check if it exists boolean exists = defaultUser.getExpandoBridge().hasAttribute(customFieldNameUserStatisticsVisibility); - + if(exists){ - + _log.debug("Custom field already exists... There is no need to create it"); - + }else{ - + _log.debug("Creating custom field " + customFieldNameUserStatisticsVisibility + " with starting value " + startingValue); - + // create defaultUser.getExpandoBridge().addAttribute(CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY, ExpandoColumnConstants.BOOLEAN, (Serializable)(true)); } - + }catch(Exception e){ _log.error("Unable to create custom field " + customFieldNameUserStatisticsVisibility); } @@ -557,12 +574,16 @@ public class UserStatisticsServiceImpl extends RemoteServiceServlet implements U private static int evaluateInformationScore(User user, boolean imageIsPresent) { int score = 0; - score += user.getJobTitle().compareTo("") != 0 ? 20 : 0; - score += user.getOpenId().compareTo("") != 0 ? 20 : 0; + if(user.getJobTitle() != null) + score += !user.getJobTitle().isEmpty() ? 20 : 0; + if(user.getOpenId() != null) + score += !user.getOpenId().isEmpty() ? 20 : 0; String summary = getSummary(user); - int lenght = summary.replace(" ", "").length(); - float partialScore = ((float)lenght / 10.0f); - score += partialScore > 20f ? 20 : (int)partialScore; + if(summary != null){ + int lenght = summary.replace(" ", "").length(); + float partialScore = ((float)lenght / 10.0f); + score += partialScore > 20f ? 20 : (int)partialScore; + } if(imageIsPresent) score += 5; @@ -576,12 +597,15 @@ public class UserStatisticsServiceImpl extends RemoteServiceServlet implements U * @return */ private static String getSummary(User user) { - String toReturn = escapeHtml(user.getComments()); - // replace all the line breaks by
- toReturn = toReturn.replaceAll("(\r\n|\n)","
"); - // then replace all the double spaces by the html version   - toReturn = toReturn.replaceAll("\\s\\s","  "); - return toReturn; + if(user.getComments() != null){ + String toReturn = escapeHtml(user.getComments()); + // replace all the line breaks by
+ toReturn = toReturn.replaceAll("(\r\n|\n)","
"); + // then replace all the double spaces by the html version   + toReturn = toReturn.replaceAll("\\s\\s","  "); + return toReturn; + }else + return null; } /** @@ -611,12 +635,18 @@ public class UserStatisticsServiceImpl extends RemoteServiceServlet implements U try{ Contact contact = user.getContact(); - score += contact.getMySpaceSn().compareTo("") != 0 ? 5 : 0; - score += contact.getTwitterSn().compareTo("") != 0 ? 5 : 0; - score += contact.getFacebookSn().compareTo("") != 0 ? 5 : 0; - score += contact.getSkypeSn().compareTo("") != 0 ? 5 : 0; - score += contact.getJabberSn().compareTo("") != 0 ? 5 : 0; - score += contact.getAimSn().compareTo("") != 0 ? 5 : 0; + if(contact.getMySpaceSn() != null) + score += !contact.getMySpaceSn().isEmpty() ? 5 : 0; + if(contact.getTwitterSn() != null) + score += !contact.getTwitterSn().isEmpty() ? 5 : 0; + if(contact.getFacebookSn() != null) + score += !contact.getFacebookSn().isEmpty() ? 5 : 0; + if(contact.getSkypeSn() != null) + score += !contact.getSkypeSn().isEmpty() ? 5 : 0; + if(contact.getJabberSn() != null) + score += !contact.getJabberSn().isEmpty() ? 5 : 0; + if(contact.getAimSn() != null) + score += !contact.getAimSn().isEmpty() ? 5 : 0; List websites = WebsiteLocalServiceUtil.getWebsites(user.getCompanyId(), "com.liferay.portal.model.Contact", contact.getContactId()); score += websites.size() > 0 ? 5 : 0; diff --git a/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/cache/CacheInterface.java b/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/cache/CacheInterface.java new file mode 100644 index 0000000..99f06f8 --- /dev/null +++ b/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/cache/CacheInterface.java @@ -0,0 +1,26 @@ +package org.gcube.portlet.user.userstatisticsportlet.server.cache; + +/** + * Statistics cache interface + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + * @param the key type + * @param the value type + */ +public interface CacheInterface { + + /** + * 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); + +} diff --git a/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/cache/CacheUtilities.java b/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/cache/CacheUtilities.java new file mode 100644 index 0000000..f23b701 --- /dev/null +++ b/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/cache/CacheUtilities.java @@ -0,0 +1,26 @@ +package org.gcube.portlet.user.userstatisticsportlet.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 if expired, otherwise + */ + public static boolean expired(long beanTimestamp, long ttl){ + + long currentTime = System.currentTimeMillis(); + + if((beanTimestamp + ttl) <= currentTime) + return true; + else + return false; + + } +} diff --git a/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/cache/CacheValueBean.java b/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/cache/CacheValueBean.java new file mode 100644 index 0000000..b5b2572 --- /dev/null +++ b/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/cache/CacheValueBean.java @@ -0,0 +1,40 @@ +package org.gcube.portlet.user.userstatisticsportlet.server.cache; + +/** + * A bean object to be used as value within statistics' caches. It contains a TTL value too. + * @author Costantino Perciante at ISTI-CNR + * (costantino.perciante@isti.cnr.it) + * + * @param the value type + */ +public class CacheValueBean { + + 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 + "]"; + } +} diff --git a/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/cache/UserInfrastructureSpaceCache.java b/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/cache/UserInfrastructureSpaceCache.java new file mode 100644 index 0000000..1292761 --- /dev/null +++ b/src/main/java/org/gcube/portlet/user/userstatisticsportlet/server/cache/UserInfrastructureSpaceCache.java @@ -0,0 +1,82 @@ +package org.gcube.portlet.user.userstatisticsportlet.server.cache; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.slf4j.LoggerFactory; + +/** + * Cache for the user's space in use within the infrastructure + * @author Costantino Perciante at ISTI-CNR + * (costantino.perciante@isti.cnr.it) + */ +public class UserInfrastructureSpaceCache implements CacheInterface { + + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(UserInfrastructureSpaceCache.class); + + /** + * The instance + */ + private static UserInfrastructureSpaceCache instance = new UserInfrastructureSpaceCache(); + + /** + * The hashmap + */ + private Map> userSpaceMap; + + /** + * Cache entry expires after EXPIRED_AFTER ms + */ + private static final long EXPIRED_AFTER = 1000 * 60 * 10; + + /** + * Private constructor + */ + private UserInfrastructureSpaceCache(){ + + userSpaceMap = new ConcurrentHashMap<>(); + + } + + /** + * Retrieve the current cache instance object + * @return + */ + public static UserInfrastructureSpaceCache getCacheInstance(){ + + return instance; + + } + + @Override + public Long get(String key) { + + if(userSpaceMap.containsKey(key)){ + + CacheValueBean bean = userSpaceMap.get(key); + + if(CacheUtilities.expired(bean.getTTL(), EXPIRED_AFTER)){ + userSpaceMap.remove(key); + logger.debug("Amount of space in the infrastructure used expired for key " + key + ", returning null"); + } + else + return bean.getValue(); + } + + return null; + + } + + @Override + public boolean insert(String key, Long value) { + + CacheValueBean newBean = new CacheValueBean(value, System.currentTimeMillis()); + + if(userSpaceMap.containsKey(key)) + userSpaceMap.remove(key); + + userSpaceMap.put(key, newBean); + + return true; + } +}