2015-12-09 14:34:41 +01:00
package org.gcube.portlet.user.userstatisticsportlet.server ;
2016-05-10 18:40:55 +02:00
import java.util.Calendar ;
2016-08-02 17:42:05 +02:00
import java.util.HashMap ;
2015-12-09 14:34:41 +01:00
import java.util.List ;
2016-08-02 17:42:05 +02:00
import java.util.Map ;
2015-12-09 14:34:41 +01:00
import org.gcube.application.framework.core.session.ASLSession ;
import org.gcube.common.homelibrary.home.HomeLibrary ;
import org.gcube.common.homelibrary.home.workspace.Workspace ;
2016-05-20 15:12:01 +02:00
import org.gcube.common.portal.PortalContext ;
2016-03-31 18:22:06 +02:00
import org.gcube.portal.custom.communitymanager.SiteManagerUtil ;
2015-12-09 14:34:41 +01:00
import org.gcube.portal.databook.server.DBCassandraAstyanaxImpl ;
import org.gcube.portal.databook.server.DatabookStore ;
2016-08-02 17:42:05 +02:00
import org.gcube.portal.databook.shared.Comment ;
2015-12-09 14:34:41 +01:00
import org.gcube.portal.databook.shared.Feed ;
import org.gcube.portlet.user.userstatisticsportlet.client.UserStatisticsService ;
2016-05-23 17:45:17 +02:00
import org.gcube.portlet.user.userstatisticsportlet.server.cache.UserInfrastructureSpaceCache ;
2015-12-09 14:34:41 +01:00
import org.gcube.portlet.user.userstatisticsportlet.shared.PostsStatsBean ;
import org.gcube.portlet.user.userstatisticsportlet.shared.UserInformation ;
2016-05-10 18:40:55 +02:00
import org.gcube.vomanagement.usermanagement.UserManager ;
import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException ;
import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault ;
import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager ;
import org.gcube.vomanagement.usermanagement.util.ManagementUtils ;
2015-12-09 14:34:41 +01:00
import org.slf4j.LoggerFactory ;
import com.google.gwt.user.server.rpc.RemoteServiceServlet ;
2016-07-11 16:02:37 +02:00
import com.liferay.portal.kernel.cache.CacheRegistryUtil ;
2015-12-09 14:34:41 +01:00
import com.liferay.portal.model.User ;
import com.liferay.portal.service.UserLocalServiceUtil ;
/ * *
* The server side implementation of the RPC service .
* /
@SuppressWarnings ( " serial " )
public class UserStatisticsServiceImpl extends RemoteServiceServlet implements UserStatisticsService {
// Logger
2016-08-03 16:26:49 +02:00
private static final org . slf4j . Logger logger = LoggerFactory . getLogger ( UserStatisticsServiceImpl . class ) ;
2015-12-09 14:34:41 +01:00
//dev user
2016-05-10 18:40:55 +02:00
public static final String defaultUserId = " test.user " ;
2015-12-09 14:34:41 +01:00
//dev vre
2016-08-03 16:26:49 +02:00
public static final String vreID = " /gcube/devsec/devVRE " ;
2015-12-09 14:34:41 +01:00
// Cassandra connection
private DatabookStore store ;
2016-05-10 18:40:55 +02:00
// custom field' name to remember action to take for the portlet deployed in the user profile
private static final String CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY = " show_user_statistics_other_people " ;
2015-12-09 14:34:41 +01:00
@Override
public void init ( ) {
2016-08-03 16:26:49 +02:00
2015-12-09 14:34:41 +01:00
// get connection to Cassandra
2016-08-03 16:26:49 +02:00
logger . debug ( " Getting connection to Cassandra.. " ) ;
2015-12-09 14:34:41 +01:00
store = new DBCassandraAstyanaxImpl ( ) ;
2016-05-23 17:45:17 +02:00
2016-05-10 18:40:55 +02:00
// add statistics option for profile pages and set to true
2016-08-03 16:26:49 +02:00
ServerUtils . createUserCustomField ( CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY , true ) ;
2015-12-09 14:34:41 +01:00
}
@Override
public void destroy ( ) {
// shutting down connection to Cassandra
2016-08-03 16:26:49 +02:00
logger . info ( " Closing connection to Cassandra " ) ;
2015-12-09 14:34:41 +01:00
store . closeConnection ( ) ;
}
@Override
2016-05-10 18:40:55 +02:00
public String getTotalSpaceInUse ( String userid ) {
2015-12-09 14:34:41 +01:00
String storageInUse = null ;
// get the session
2016-08-03 16:26:49 +02:00
ASLSession session = ServerUtils . getASLSession ( this . getThreadLocalRequest ( ) . getSession ( ) ) ;
2015-12-09 14:34:41 +01:00
2016-05-10 18:40:55 +02:00
// username in the session
2015-12-09 14:34:41 +01:00
String userName = session . getUsername ( ) ;
2016-05-10 18:40:55 +02:00
// retrieve statistics of...
String statisticsOfUsername = userName ;
if ( userid ! = null & & ! userid . equals ( userName ) )
statisticsOfUsername = userid ;
2015-12-09 14:34:41 +01:00
//in case the portal is restarted and you have the social home open it will get test.user (no callback to set session info)
//this check just return nothing if that happens
2016-05-10 18:40:55 +02:00
if ( userName . compareTo ( defaultUserId ) = = 0 ) {
2015-12-09 14:34:41 +01:00
2016-08-03 16:26:49 +02:00
logger . debug ( " Found " + userName + " returning nothing " ) ;
2015-12-09 14:34:41 +01:00
return null ;
2016-04-06 15:42:41 +02:00
2015-12-09 14:34:41 +01:00
} else {
2016-08-03 16:26:49 +02:00
logger . debug ( " Getting " + statisticsOfUsername + " amount of workspace in use. " ) ;
2015-12-09 14:34:41 +01:00
try {
2016-04-06 15:42:41 +02:00
2015-12-09 14:34:41 +01:00
long init = System . currentTimeMillis ( ) ;
2016-04-06 15:42:41 +02:00
2016-05-23 17:45:17 +02:00
// 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 ) {
2016-08-03 16:26:49 +02:00
logger . debug ( " Information not available in the cache, asking workspace " ) ;
2016-05-23 17:45:17 +02:00
Workspace workspace = HomeLibrary . getUserWorkspace ( statisticsOfUsername ) ;
storageInUseLong = workspace . getDiskUsage ( ) ;
2016-08-03 16:26:49 +02:00
logger . debug ( " Put information in the cache " ) ;
2016-05-23 17:45:17 +02:00
cacheWorkspace . insert ( statisticsOfUsername , storageInUseLong ) ;
}
2016-08-03 16:26:49 +02:00
storageInUse = ServerUtils . formatFileSize ( storageInUseLong ) ;
2016-04-06 15:42:41 +02:00
2015-12-09 14:34:41 +01:00
long end = System . currentTimeMillis ( ) ;
2016-08-03 16:26:49 +02:00
logger . debug ( " [USER-STATISTICS] time taken to retrieve user space is " + ( end - init ) + " ms " ) ;
2015-12-09 14:34:41 +01:00
} catch ( Exception e ) {
2016-08-03 16:26:49 +02:00
logger . error ( " Unable to retrieve workspace information! " ) ;
2015-12-09 14:34:41 +01:00
}
}
return storageInUse ;
}
@Override
2016-05-10 18:40:55 +02:00
public int getProfileStrength ( String userid ) {
2015-12-09 14:34:41 +01:00
int profileStrenght = - 1 ;
// get the session
2016-08-03 16:26:49 +02:00
ASLSession session = ServerUtils . getASLSession ( this . getThreadLocalRequest ( ) . getSession ( ) ) ;
2015-12-09 14:34:41 +01:00
2016-05-10 18:40:55 +02:00
// username
2015-12-09 14:34:41 +01:00
String userName = session . getUsername ( ) ;
2016-05-10 18:40:55 +02:00
// retrieve statistics of...
String statisticsOfUsername = userName ;
if ( userid ! = null & & ! userid . equals ( userName ) )
statisticsOfUsername = userid ;
2015-12-09 14:34:41 +01:00
//in case the portal is restarted and you have the social home open it will get test.user (no callback to set session info)
//this check just return nothing if that happens
2016-05-10 18:40:55 +02:00
if ( userName . compareTo ( defaultUserId ) = = 0 ) {
2016-08-03 16:26:49 +02:00
logger . debug ( " Found " + userName + " returning nothing " ) ;
2015-12-09 14:34:41 +01:00
return profileStrenght ;
} else {
// valuate profile strength
2016-08-03 16:26:49 +02:00
if ( ServerUtils . isWithinPortal ( ) ) {
2015-12-09 14:34:41 +01:00
try {
2016-05-23 17:45:17 +02:00
long init = System . currentTimeMillis ( ) ;
2016-08-02 17:42:05 +02:00
2015-12-09 14:34:41 +01:00
// check if the avatar is present
2016-05-10 18:40:55 +02:00
boolean avatarPresent = ( new LiferayUserManager ( ) . getUserAvatarBytes ( statisticsOfUsername ) ! = null ) ;
2015-12-09 14:34:41 +01:00
2016-05-10 18:40:55 +02:00
User user = UserLocalServiceUtil . getUserByScreenName ( SiteManagerUtil . getCompany ( ) . getCompanyId ( ) , statisticsOfUsername ) ;
2016-08-03 16:26:49 +02:00
profileStrenght = ServerUtils . evaluateProfileStrenght ( user , avatarPresent ) ;
2016-04-06 15:42:41 +02:00
2015-12-09 14:34:41 +01:00
long end = System . currentTimeMillis ( ) ;
2016-08-03 16:26:49 +02:00
logger . debug ( " [USER-STATISTICS] time taken to evaluate user profile strenght is " + ( end - init ) + " ms " ) ;
2015-12-09 14:34:41 +01:00
} catch ( Exception e ) {
2016-08-03 16:26:49 +02:00
logger . error ( " Profile strenght evaluation failed!! " + e . toString ( ) , e ) ;
2015-12-09 14:34:41 +01:00
}
}
}
return profileStrenght ;
}
@Override
2016-05-10 18:40:55 +02:00
public UserInformation getUserSettings ( String userid ) {
2015-12-09 14:34:41 +01:00
// get the session
2016-08-03 16:26:49 +02:00
ASLSession session = ServerUtils . getASLSession ( this . getThreadLocalRequest ( ) . getSession ( ) ) ;
2015-12-09 14:34:41 +01:00
2016-05-10 18:40:55 +02:00
//username of the asl session
2015-12-09 14:34:41 +01:00
String userName = session . getUsername ( ) ;
2016-05-10 18:40:55 +02:00
// retrieve statistics of...
String statisticsOfUsername = userName ;
// is he the owner of the profile?
boolean isOwner = false ;
// can we show this profile to other people?
boolean isProfileShowable = true ;
if ( userid = = null | | ( userid ! = null & & userid . equals ( userName ) ) ) {
isOwner = true ;
isProfileShowable = checkUserPrivacyOption ( userName ) ;
}
if ( userid ! = null & & ! userid . equals ( userName ) ) {
// the stastics to show will be of the userid
statisticsOfUsername = userid ;
isProfileShowable = checkUserPrivacyOption ( statisticsOfUsername ) ;
2016-08-02 17:42:05 +02:00
2016-08-03 16:26:49 +02:00
logger . info ( " Is profile showable for user " + userid + " " + isProfileShowable ) ;
2016-05-10 18:40:55 +02:00
}
2015-12-09 14:34:41 +01:00
//in case the portal is restarted and you have the social home open it will get test.user (no callback to set session info)
//this check just return nothing if that happens
2016-05-10 18:40:55 +02:00
if ( userName . compareTo ( defaultUserId ) = = 0 ) {
2016-08-03 16:26:49 +02:00
logger . debug ( " Found " + userName + " returning nothing " ) ;
2015-12-09 14:34:41 +01:00
return null ;
}
2016-08-03 16:26:49 +02:00
if ( ServerUtils . isWithinPortal ( ) ) {
2016-05-12 10:29:44 +02:00
// If the user is in the root panel (or is visiting a profile page), we have to send him the overall number of posts made, comments/likes(received) and the space in use.
2015-12-09 14:34:41 +01:00
// Otherwise we have to filter on the vre.
2016-08-03 16:26:49 +02:00
boolean isInfrastructure = ServerUtils . isInfrastructureScope ( userid , this . getThreadLocalRequest ( ) . getSession ( ) ) ;
logger . debug ( " User scope is " + ( isInfrastructure ? " the whole infrastucture " : " a VRE " ) ) ;
2015-12-09 14:34:41 +01:00
// get path of the avatar
2016-05-10 18:40:55 +02:00
UserManager um = new LiferayUserManager ( ) ;
String thumbnailURL = null ;
try {
thumbnailURL = um . getUserByUsername ( statisticsOfUsername ) . getUserAvatarURL ( ) ;
} catch ( UserManagementSystemException e ) {
2016-08-03 16:26:49 +02:00
logger . error ( " Unable to retrieve avatar url for user " + statisticsOfUsername , e ) ;
2016-05-10 18:40:55 +02:00
} catch ( UserRetrievalFault e ) {
2016-08-03 16:26:49 +02:00
logger . error ( " Unable to retrieve avatar url for user " + statisticsOfUsername , e ) ;
2016-05-10 18:40:55 +02:00
}
2016-08-03 16:26:49 +02:00
logger . debug ( statisticsOfUsername + " avatar has url " + thumbnailURL ) ;
2015-12-09 14:34:41 +01:00
// get the vre (if not in the infrastructure)
String actualVre = null ;
if ( ! isInfrastructure ) {
String [ ] temp = session . getScope ( ) . split ( " / " ) ;
actualVre = temp [ temp . length - 1 ] ;
}
2016-05-23 17:45:17 +02:00
2016-05-20 15:12:01 +02:00
// page landing
String pageLanding = PortalContext . getConfiguration ( ) . getSiteLandingPagePath ( getThreadLocalRequest ( ) ) ;
2015-12-09 14:34:41 +01:00
2016-05-20 15:12:01 +02:00
UserInformation bean = new UserInformation ( isInfrastructure , thumbnailURL , userName , actualVre , isOwner , isProfileShowable ) ;
bean . setCurrentPageLanding ( pageLanding ) ;
return bean ;
2016-05-10 18:40:55 +02:00
}
else return new UserInformation ( true , null , userName , vreID , true , true ) ;
}
/ * *
* Check privacy option for user ' s own statistics
* @param username
* @return
* /
private boolean checkUserPrivacyOption ( String username ) {
try {
// set permission checker
2016-08-03 16:26:49 +02:00
ServerUtils . setPermissionChecker ( ) ;
2016-08-02 17:42:05 +02:00
2016-07-11 16:02:37 +02:00
//needed to avoid cache use by liferay API
CacheRegistryUtil . clear ( ) ;
2016-05-10 18:40:55 +02:00
User user = UserLocalServiceUtil . getUserByScreenName ( ManagementUtils . getCompany ( ) . getCompanyId ( ) , username ) ;
// the user has not decided yet
if ( ! user . getExpandoBridge ( ) . hasAttribute ( CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY ) )
return true ;
return ( boolean ) user . getExpandoBridge ( ) . getAttribute ( CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY ) ;
} catch ( Exception e ) {
2016-08-03 16:26:49 +02:00
logger . error ( " Unable to retrieve user's privacy option for his statistics " ) ;
2016-05-10 18:40:55 +02:00
return true ;
2015-12-09 14:34:41 +01:00
}
}
@Override
2016-05-10 18:40:55 +02:00
public PostsStatsBean getPostsStats ( String userid ) {
2016-04-06 15:42:41 +02:00
2015-12-09 14:34:41 +01:00
// get the session
2016-08-03 16:26:49 +02:00
ASLSession session = ServerUtils . getASLSession ( this . getThreadLocalRequest ( ) . getSession ( ) ) ;
2015-12-09 14:34:41 +01:00
//username
String userName = session . getUsername ( ) ;
2016-05-10 18:40:55 +02:00
// retrieve statistics of...
String statisticsOfUsername = userName ;
if ( userid ! = null & & ! userid . equals ( userName ) )
statisticsOfUsername = userid ;
2015-12-09 14:34:41 +01:00
//in case the portal is restarted and you have the social home open it will get test.user (no callback to set session info)
//this check just return nothing if that happens
2016-05-10 18:40:55 +02:00
if ( userName . compareTo ( defaultUserId ) = = 0 ) {
2016-08-03 16:26:49 +02:00
logger . debug ( " Found " + userName + " returning nothing " ) ;
2015-12-09 14:34:41 +01:00
return null ;
}
2016-08-02 17:42:05 +02:00
long feedsMade = 0 , likesGot = 0 , commentsGot = 0 , commentsMade = 0 , likesMade = 0 ;
2015-12-09 14:34:41 +01:00
// check if the user is or not in a VRE
2016-08-03 16:26:49 +02:00
boolean isInfrastructure = ServerUtils . isInfrastructureScope ( userid , this . getThreadLocalRequest ( ) . getSession ( ) ) ;
2015-12-09 14:34:41 +01:00
// date corresponding to one year ago
2016-05-10 18:40:55 +02:00
Calendar oneYearAgo = Calendar . getInstance ( ) ;
oneYearAgo . set ( Calendar . YEAR , oneYearAgo . get ( Calendar . YEAR ) - 1 ) ;
2015-12-09 14:34:41 +01:00
2016-08-03 16:26:49 +02:00
logger . debug ( " Reference time is " + oneYearAgo . getTime ( ) ) ;
2015-12-09 14:34:41 +01:00
try {
long init = System . currentTimeMillis ( ) ;
2016-08-03 16:26:49 +02:00
logger . debug ( " Getting " + statisticsOfUsername + " feeds in the last year. " ) ;
2015-12-09 14:34:41 +01:00
2016-08-02 17:42:05 +02:00
// retrieve the most recent user's feeds
2016-05-10 18:40:55 +02:00
List < Feed > userFeeds = store . getRecentFeedsByUserAndDate ( statisticsOfUsername , oneYearAgo . getTime ( ) . getTime ( ) ) ;
2015-12-09 14:34:41 +01:00
2016-08-03 16:26:49 +02:00
logger . debug ( " Evaluating number of comments and likes of " + statisticsOfUsername + " 's feeds. " ) ;
2015-12-09 14:34:41 +01:00
for ( Feed feed : userFeeds ) {
try {
// check if the user is in the root, if not check if the VRE of the feed is the current one
if ( ! isInfrastructure & & ! feed . getVreid ( ) . equals ( session . getScope ( ) ) )
continue ;
// increment feeds number
2016-08-02 17:42:05 +02:00
feedsMade + + ;
2015-12-09 14:34:41 +01:00
//increment number of post replies and likes
2016-08-02 17:42:05 +02:00
commentsGot + = Integer . parseInt ( feed . getCommentsNo ( ) ) ;
likesGot + = Integer . parseInt ( feed . getLikesNo ( ) ) ;
2015-12-09 14:34:41 +01:00
} catch ( NumberFormatException e ) {
2016-08-03 16:26:49 +02:00
logger . error ( e . toString ( ) ) ;
2015-12-09 14:34:41 +01:00
}
}
2016-08-02 17:42:05 +02:00
// retrieve the most recent user's liked feeds
List < Feed > recentLikedFeeds = store . getRecentLikedFeedsByUserAndDate ( statisticsOfUsername , oneYearAgo . getTime ( ) . getTime ( ) ) ;
for ( Feed feed : recentLikedFeeds ) {
// check if the user is in the root, if not check if the VRE of the feed is the current one
if ( ! isInfrastructure & & ! feed . getVreid ( ) . equals ( session . getScope ( ) ) )
continue ;
likesMade + + ; // no further check is needed since the user can do like just one time per feed
}
// retrieve the most recent user's comments
List < Comment > recentComments = store . getRecentCommentsByUserAndDate ( statisticsOfUsername , oneYearAgo . getTime ( ) . getTime ( ) ) ;
Map < String , Feed > parentFeeds = new HashMap < String , Feed > ( ) ;
for ( Comment comment : recentComments ) {
Feed parentFeed = null ;
if ( ! parentFeeds . containsKey ( comment . getFeedid ( ) ) ) {
parentFeed = store . readFeed ( comment . getFeedid ( ) ) ;
parentFeeds . put ( comment . getFeedid ( ) , parentFeed ) ;
}
parentFeed = parentFeeds . get ( comment . getFeedid ( ) ) ;
2016-08-03 16:26:49 +02:00
2016-08-02 17:42:05 +02:00
// check if the user is in the root, if not check if the VRE of the feed is the current one
if ( ! isInfrastructure & & ! parentFeed . getVreid ( ) . equals ( session . getScope ( ) ) )
continue ;
commentsMade + + ;
}
2015-12-09 14:34:41 +01:00
long end = System . currentTimeMillis ( ) ;
2016-04-06 15:42:41 +02:00
2016-08-03 16:26:49 +02:00
logger . debug ( " [USER-STATISTICS] time taken to retrieve statistics is " + ( end - init ) + " ms " ) ;
logger . debug ( " Total number of feeds made (after time filtering) of " + statisticsOfUsername + " is " + feedsMade ) ;
logger . debug ( " Total number of likes got (after time filtering) for " + statisticsOfUsername + " is " + likesGot ) ;
logger . debug ( " Total number of comments got (after time filtering) for " + statisticsOfUsername + " is " + commentsGot ) ;
logger . debug ( " Total number of likes made (after time filtering) for " + statisticsOfUsername + " is " + likesMade ) ;
logger . debug ( " Total number of comments made (after time filtering) for " + statisticsOfUsername + " is " + commentsMade ) ;
2015-12-09 14:34:41 +01:00
} catch ( Exception e ) {
2016-08-03 16:26:49 +02:00
logger . error ( e . toString ( ) ) ;
2015-12-09 14:34:41 +01:00
return null ;
}
// return the object
2016-08-02 17:42:05 +02:00
return new PostsStatsBean ( feedsMade , likesGot , commentsGot , commentsMade , likesMade ) ;
2015-12-09 14:34:41 +01:00
}
2016-05-10 18:40:55 +02:00
@Override
public void setShowMyOwnStatisticsToOtherPeople ( boolean show ) {
2016-08-03 16:26:49 +02:00
if ( ServerUtils . isWithinPortal ( ) ) {
2016-05-10 18:40:55 +02:00
2016-08-03 16:26:49 +02:00
ASLSession session = ServerUtils . getASLSession ( this . getThreadLocalRequest ( ) . getSession ( ) ) ;
2016-05-10 18:40:55 +02:00
String username = session . getUsername ( ) ;
//in case the portal is restarted and you have the social home open it will get test.user (no callback to set session info)
//this check just return nothing if that happens
if ( username . compareTo ( defaultUserId ) = = 0 ) {
2016-08-03 16:26:49 +02:00
logger . debug ( " Found " + username + " returning nothing " ) ;
2016-05-10 18:40:55 +02:00
return ;
}
try {
// set permission checker
2016-08-03 16:26:49 +02:00
ServerUtils . setPermissionChecker ( ) ;
2016-08-02 17:42:05 +02:00
2016-07-11 16:02:37 +02:00
//needed to avoid cache use by liferay API
CacheRegistryUtil . clear ( ) ;
2016-05-10 18:40:55 +02:00
2016-08-03 16:26:49 +02:00
logger . debug ( " User " + username + ( show ? " want to show " : " doesn't want to show " ) + " his statistics " ) ;
2016-05-10 18:40:55 +02:00
User user = UserLocalServiceUtil . getUserByScreenName ( ManagementUtils . getCompany ( ) . getCompanyId ( ) , username ) ;
boolean hasAttribute = user . getExpandoBridge ( ) . hasAttribute ( CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY ) ;
if ( hasAttribute ) {
// set the new value
2016-08-03 16:26:49 +02:00
logger . debug ( " Setting custom field value to " + show + " for user " + username ) ;
2016-05-10 18:40:55 +02:00
// set the current value
user . getExpandoBridge ( ) . setAttribute ( CUSTOM_FIELD_NAME_USER_STATISTICS_VISIBILITY , show ) ;
}
2016-05-23 17:45:17 +02:00
2016-05-10 18:40:55 +02:00
} catch ( Exception e ) {
2016-08-03 16:26:49 +02:00
logger . error ( " Unable to check user's privacy for his statistics " , e ) ;
2016-05-10 18:40:55 +02:00
}
}
}
2015-12-09 14:34:41 +01:00
}