package org.theospi.portfolio.presentation.support;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.memory.api.MemoryService;
import org.sakaiproject.metaobj.shared.mgt.AgentManager;
import org.sakaiproject.metaobj.shared.model.Agent;
import org.theospi.event.EventConstants;
import org.theospi.event.EventService;
import org.theospi.portfolio.presentation.control.UserAgentComparator;
import org.theospi.portfolio.presentation.model.Presentation;
import org.theospi.portfolio.presentation.PresentationFunctionConstants;
public class PresentationShareUserService {
protected final Log logger = LogFactory.getLog(getClass());
private UserAgentComparator userAgentComparator = new UserAgentComparator();
private MemoryService memoryService;
private PresentationService presentationService;
private EventService eventService;
private AgentManager agentManager;
/** A site cache. */
private ShareUserCacheImpl shareUserCache = null;
/** The # seconds to cache the site queries. 0 disables the cache. */
protected int cacheSeconds = 60 * 5;
public void setCacheSeconds(String time)
{
cacheSeconds = Integer.parseInt(time);
}
public void setCacheMinutes(String time)
{
cacheSeconds = Integer.parseInt(time) * 60;
}
public void init() {
if (cacheSeconds > 0)
{
shareUserCache = new ShareUserCacheImpl(memoryService, cacheSeconds, PresentationFunctionConstants.PRESENTATION_SHARE_USER);
}
}
/**
* Force loading the cache from the database whether the cache has expired or not
*
* @param presentationId
*/
public void loadCache(String presentationId) {
Presentation presentation = presentationService.getPresentation(presentationId, false);
getSharedList(presentation, true);
}
/**
* Clone the SharedList so that we can avoid the concurrency exception
*
* @param list
* @return
*/
private List cloneArrayList(List list) {
if (list == null || ! (list instanceof ArrayList)) {
logger.debug("*** cannot clone list **** - " + list);
return list;
}
return (List)((ArrayList) list).clone();
}
public void setSharedList(List sharedList, Presentation presentation) {
shareUserCache.put(PresentationFunctionConstants.PRESENTATION_SHARE_USER_CACHE_PREFIX + presentation.getId().getValue(),
sharedList);
}
public List getSharedList(Presentation presentation) {
return getSharedList(presentation, false);
}
public List getSharedList(Presentation presentation, boolean forceDbReload) {
List sharedList = (List) shareUserCache.get(PresentationFunctionConstants.PRESENTATION_SHARE_USER_CACHE_PREFIX + presentation.getId().getValue());
if (sharedList == null || forceDbReload) {
logger.debug("PresentationShareUserService - Pulling from db");
sharedList = presentationService.getShareList( presentation );
Collections.sort(sharedList, userAgentComparator);
setSharedList(sharedList, presentation);
}
sharedList = cloneArrayList(sharedList); // to prevent concurrent access to cache
return sharedList;
}
/**
*
* @param presentationId
* @param userId
* @return null if user not found
*/
public Agent getUserAgentFromCache(String presentationId, String userId) {
if (presentationId == null || userId == null) {
return null;
}
Presentation presentation = presentationService.getPresentation(presentationId, false);
List<Agent> sharedList = getSharedList(presentation, false);
for(Agent agent: sharedList) {
if (agent.getId().getValue().equals(userId)) {
return agent;
}
}
return null;
}
/**
* Send the add user event to the cluster
*
* @param presentationId
* @param userId
*/
public void triggerAddUserEvent(String presentationId, String userId) {
eventService.postEvent(EventConstants.EVENT_PRESENTATION_USER_ADD,
encodeReference(presentationId, userId));
}
/**
* Add the specified user into the shared list cache for the presentation
* It will do nothing is the user already exists int he cache for that presentation
*
* @param presentationId
* @param userId
*/
public void addUser(String presentationId, String userId) {
if (presentationId == null || userId == null) {
return;
}
Presentation presentation = presentationService.getPresentation(presentationId, false);
if (presentation != null) {
List<Agent> sharedList = getSharedList(presentation, false);
Agent existingAgent = getUserAgentFromCache(presentationId, userId);
if (existingAgent == null) {
Agent agent = agentManager.getAgent(userId);
if (agent != null) {
sharedList.add(agent);
Collections.sort(sharedList, userAgentComparator);
setSharedList(sharedList, presentation);
}
}
}
}
/**
* Send the delete user event to the cluster
*
* @param presentationId
* @param userId
*/
public void triggerRemoveUserEvent(String presentationId, String userId) {
eventService.postEvent(EventConstants.EVENT_PRESENTATION_USER_DELETE,
encodeReference(presentationId, userId));
}
/**
* Remove the specified user into the shared list cache for the presentation
* It will do nothing is the user does not already exists in the cache for that presentation
*
* @param presentationId
* @param userId
*/
public void removeUser(String presentationId, String userId) {
if (presentationId == null || userId == null) {
return;
}
Presentation presentation = presentationService.getPresentation(presentationId, false);
if (presentation != null) {
Agent agent = getUserAgentFromCache(presentationId, userId);
if (agent != null) {
List<Agent> sharedList = getSharedList(presentation, false);
sharedList.remove(agent);
setSharedList(sharedList, presentation);
return;
}
}
}
/**
* Returns the presentationId from the shared list cache event reference (from the observer)
*
* @param reference
* @return
*/
public static String getPresentationIdFromReference (String reference) {
if (reference == null ||
reference.indexOf(PresentationFunctionConstants.PRESENTATION_SHARE_USER_EVENT_REFERENCE_PREFIX) == -1) {
return null;
}
String presentationId = null;
int firstIndex = reference.indexOf(PresentationFunctionConstants.PRESENTATION_SHARE_USER_EVENT_REFERENCE_DELIM, 1);
int lastIndex = reference.lastIndexOf(PresentationFunctionConstants.PRESENTATION_SHARE_USER_EVENT_REFERENCE_DELIM);
if (firstIndex == -1 || lastIndex == -1 || firstIndex+1 > reference.length()) {
return null;
}
presentationId = reference.substring(firstIndex+1, lastIndex);
return presentationId;
}
/**
* Returns the userId from the shared list cache event reference (from the observer)
*
* @param reference
* @return
*/
public static String getUserIdFromReference (String reference) {
if (reference == null ||
reference.indexOf(PresentationFunctionConstants.PRESENTATION_SHARE_USER_EVENT_REFERENCE_PREFIX) == -1) {
return null;
}
String userId = null;
int lastIndex = reference.lastIndexOf(PresentationFunctionConstants.PRESENTATION_SHARE_USER_EVENT_REFERENCE_DELIM);
if (lastIndex == -1 || lastIndex+1 > reference.length()) {
return null;
}
userId = reference.substring(lastIndex+1);
return userId;
}
/**
* Take a presentationId and userId and create an event reference
*
* @param presentationId
* @param userId
* @return reference used for the event trigger
*/
public static String encodeReference(String presentationId, String userId) {
if (presentationId == null || userId == null ||
presentationId.indexOf(PresentationFunctionConstants.PRESENTATION_SHARE_USER_EVENT_REFERENCE_DELIM) != -1 ||
userId.indexOf(PresentationFunctionConstants.PRESENTATION_SHARE_USER_EVENT_REFERENCE_DELIM) != -1) {
return null;
}
String reference = "";
reference = PresentationFunctionConstants.PRESENTATION_SHARE_USER_EVENT_REFERENCE_DELIM + PresentationFunctionConstants.PRESENTATION_SHARE_USER_EVENT_REFERENCE_PREFIX +
PresentationFunctionConstants.PRESENTATION_SHARE_USER_EVENT_REFERENCE_DELIM + presentationId.trim() +
PresentationFunctionConstants.PRESENTATION_SHARE_USER_EVENT_REFERENCE_DELIM + userId.trim();
return reference;
}
public MemoryService getMemoryService() {
return memoryService;
}
public void setMemoryService(MemoryService memoryService) {
this.memoryService = memoryService;
}
public PresentationService getPresentationService() {
return presentationService;
}
public void setPresentationService(PresentationService presentationService) {
this.presentationService = presentationService;
}
public EventService getEventService() {
return eventService;
}
public void setEventService(EventService eventService) {
this.eventService = eventService;
}
public AgentManager getAgentManager() {
return agentManager;
}
public void setAgentManager(AgentManager agentManager) {
this.agentManager = agentManager;
}
}