<commit_before>package org.sakaiproject.component.app.messageforums;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.sakaiproject.api.app.messageforums.Area;
import org.sakaiproject.api.app.messageforums.DiscussionForumService;
import org.sakaiproject.api.app.messageforums.MessageForumsMessageManager;
import org.sakaiproject.api.app.messageforums.MessageForumsTypeManager;
import org.sakaiproject.api.app.messageforums.SynopticMsgcntrItem;
import org.sakaiproject.api.app.messageforums.SynopticMsgcntrManager;
import org.sakaiproject.api.app.messageforums.ui.DiscussionForumManager;
import org.sakaiproject.api.app.messageforums.ui.PrivateMessageManager;
import org.sakaiproject.api.app.messageforums.ui.UIPermissionsManager;
import org.sakaiproject.authz.api.Member;
import org.sakaiproject.authz.cover.SecurityService;
import org.sakaiproject.component.app.messageforums.dao.hibernate.SynopticMsgcntrItemImpl;
import org.sakaiproject.db.cover.SqlService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.cover.SiteService;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class SynopticMsgcntrManagerImpl extends HibernateDaoSupport implements SynopticMsgcntrManager {
	
	private static final Log LOG = LogFactory.getLog(SynopticMsgcntrManagerImpl.class);
	private static final String QUERY_WORKSPACE_SYNOPTIC_ITEMS = "findWorkspaceSynopticMsgcntrItems";
	private static final String QUERY_SITE_SYNOPTIC_ITEMS = "findSiteSynopticMsgcntrItems";
	private static final String QUERY_UPDATE_ALL_SITE_TITLES = "updateSiteTitles";

	private HashMap mfPageInSiteMap, sitesMap;
	// transient variable for when on home page of site
	private transient DecoratedCompiledMessageStats siteContents;
	private MessageForumsMessageManager messageManager;
	private UIPermissionsManager uiPermissionsManager;
	private PrivateMessageManager pvtMessageManager;
	private MessageForumsTypeManager typeManager;
	private DiscussionForumManager forumManager;
	
	

	
	public SynopticMsgcntrManagerImpl() {}
	
	public void init() {
		LOG.info("init()");
	}

	public List<SynopticMsgcntrItem> getWorkspaceSynopticMsgcntrItems(final String userId) {

		HibernateCallback hcb = new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query q = session.getNamedQuery(QUERY_WORKSPACE_SYNOPTIC_ITEMS);
				q.setParameter("userId", userId, Hibernate.STRING);
				return q.list();
			}
		};

		return (List<SynopticMsgcntrItem>) getHibernateTemplate().execute(hcb);	  
	}

	public SynopticMsgcntrItem getSiteSynopticMsgcntrItem(final String userId, final String siteId) {

		HibernateCallback hcb = new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query q = session.getNamedQuery(QUERY_SITE_SYNOPTIC_ITEMS);
				q.setParameter("userId", userId, Hibernate.STRING);
				q.setParameter("siteId", siteId, Hibernate.STRING);
				return q.uniqueResult();
			}
		};

		return (SynopticMsgcntrItem) getHibernateTemplate().execute(hcb);	  
	}

	public SynopticMsgcntrItem createSynopticMsgcntrItem(String userId, String siteId, String siteTitle){
		return new SynopticMsgcntrItemImpl(userId, siteId, siteTitle);
	}

	public void saveSynopticMsgcntrItem(SynopticMsgcntrItem item){
		getHibernateTemplate().saveOrUpdate(item);
	}
	
	public void deleteSynopticMsgcntrItem(SynopticMsgcntrItem item){
		getHibernateTemplate().delete(item);
	}
	
	public void incrementMessagesSynopticToolInfo(String userId, String siteId){
		incrementSynopticToolInfo(userId, siteId, true);
	}
	
	public void incrementForumSynopticToolInfo(String userId, String siteId){
		incrementSynopticToolInfo(userId, siteId, false);
	}
	
	private void incrementSynopticToolInfo(String userId, String siteId, boolean messages){
		  SynopticMsgcntrItem item = getSiteSynopticMsgcntrItem(userId, siteId);
		  if(item == null){
			  //item does not exist, call the reset function to set the 
			  //actually number of unread messages instead of incrementing
			 resetMessagesAndForumSynopticInfo(userId, siteId);
		  }else{
			  if(messages)
				  item.incrementNewMessagesCount();
			  else
				  item.incrementNewForumCount();
			  saveSynopticMsgcntrItem(item);
		  }
	}
	
	public void decrementMessagesSynopticToolInfo(String userId, String siteId){
		decrementSynopticToolInfo(userId, siteId, true);
	}
	
	public void decrementForumSynopticToolInfo(String userId, String siteId){
		decrementSynopticToolInfo(userId, siteId, false);
	}
	
	private void decrementSynopticToolInfo(String userId, String siteId, boolean messages){
		  SynopticMsgcntrItem item = getSiteSynopticMsgcntrItem(userId, siteId);
		  if(item == null){
			  //item does not exist, call the reset function to set the 
			  //actually number of unread messages instead of decrementing
			  resetMessagesAndForumSynopticInfo(userId, siteId);
		  }else{
			  if(messages)
				  item.decrementNewMessagesCount();
			  else
				  item.decrementNewForumCount();
			  saveSynopticMsgcntrItem(item);
		  }		 
	}
	
	
	public void resetMessagesAndForumSynopticInfo(String userId, String siteId) {

		DecoratedCompiledMessageStats dcmStats = this.getSiteInfo(siteId,
				userId);

		SynopticMsgcntrItem item = getSiteSynopticMsgcntrItem(userId, siteId);
		if (item == null) {
			SynopticMsgcntrItem synopticMsgcntrItem = createSynopticMsgcntrItem(
					userId, siteId, dcmStats.getSiteName());
			synopticMsgcntrItem.setNewMessagesCount(dcmStats
					.getUnreadPrivateAmt());
			synopticMsgcntrItem.setNewForumCount(dcmStats.getUnreadForumsAmt());

			saveSynopticMsgcntrItem(synopticMsgcntrItem);
		} else {
			item.setNewMessagesCount(dcmStats.getUnreadPrivateAmt());
			item.setMessagesLastVisitToCurrentDt();

			item.setNewForumCount(dcmStats.getUnreadForumsAmt());
			item.setForumLastVisitToCurrentDt();

			saveSynopticMsgcntrItem(item);
		}
	}

	public void setMessagesSynopticInfoHelper(String userId, String siteId, int newMessageCount){
		setSynopticInfoHelper(userId, siteId, true, newMessageCount);
	}
	
	public void setForumSynopticInfoHelper(String userId, String siteId, int newMessageCount){
		setSynopticInfoHelper(userId, siteId, false, newMessageCount);
	}
	
	private void setSynopticInfoHelper(String userId, String siteId, boolean messages, int newMessageCount){
		//this could be an anon access
		if (userId == null && forumManager.getAnonRole()) {
			return;
		}
		
		SynopticMsgcntrItem item = getSiteSynopticMsgcntrItem(userId, siteId);
		if(item == null){
			//item does not exist, call the reset function to set the 
			//actually number of unread messages instead of decrementing
			resetMessagesAndForumSynopticInfo(userId, siteId);
		}else{
			if(messages){
				item.setNewMessagesCount(newMessageCount);				
				item.setMessagesLastVisitToCurrentDt();
			}else{
				item.setNewForumCount(newMessageCount);
				item.setForumLastVisitToCurrentDt();
			}
			saveSynopticMsgcntrItem(item);
		}
	}
	
	/*
	 * Update Difference will get the existing count and add the difference (if negative, then its a subtract mathamatically)
	 */
	
	public void updateDifferenceMessagesSynopticInfoHelper(String userId, String siteId, int differenceCount){
		updateDifferenceSynopticInfoHelper(userId, siteId, true, differenceCount);
	}
	
	public void updateDifferenceForumSynopticInfoHelper(String userId, String siteId, int differenceCount){
		updateDifferenceSynopticInfoHelper(userId, siteId, false, differenceCount);
	}
	
	private void updateDifferenceSynopticInfoHelper(String userId, String siteId, boolean messages, int differenceCount){
		SynopticMsgcntrItem item = getSiteSynopticMsgcntrItem(userId, siteId);
		if(item == null){
			//item does not exist, call the reset function to set the 
			//actually number of unread messages instead of decrementing
			resetMessagesAndForumSynopticInfo(userId, siteId);
		}else{
			if(messages){
				int newCount = item.getNewMessagesCount() + differenceCount;
				if(newCount < 0){
					newCount = 0;
				}
				item.setNewMessagesCount(newCount);				
				item.setMessagesLastVisitToCurrentDt();
			}else{
				int newCount = item.getNewForumCount() + differenceCount;
				if(newCount < 0){
					newCount = 0;
				}
				item.setNewForumCount(newCount);
				item.setForumLastVisitToCurrentDt();
			}
			saveSynopticMsgcntrItem(item);
		}
	}
	
	
	public void createOrUpdateSynopticToolInfo(String userId, String siteId, String siteTitle, int unreadMessageCount, int unreadForumCount){	
		SynopticMsgcntrItem item = getSiteSynopticMsgcntrItem(userId, siteId);
		 if(item == null){
			 SynopticMsgcntrItem synopticMsgcntrItem = createSynopticMsgcntrItem(userId, siteId, siteTitle);	
			 synopticMsgcntrItem.setNewMessagesCount(unreadMessageCount);
			 synopticMsgcntrItem.setNewForumCount(unreadForumCount);

			 saveSynopticMsgcntrItem(synopticMsgcntrItem);								
		 }else{
			 item.setNewMessagesCount(unreadMessageCount);				
			 item.setMessagesLastVisitToCurrentDt();

			 item.setNewForumCount(unreadForumCount);
			 item.setForumLastVisitToCurrentDt();
			 saveSynopticMsgcntrItem(item);
			 if(item.getSiteTitle() == null || (item.getSiteTitle() != null && !item.getSiteTitle().equals(siteTitle))){
				 updateAllSiteTitles(siteId, siteTitle);
			 }
		 }
	}
	
	
	
	/**
	 * @return 
	 * 		DecoratedCompiledMessageStats for a single site
	 */
	public DecoratedCompiledMessageStats getSiteInfo(String siteId, String userId) {
		return getSiteContents(siteId, userId);
	}
	
	public int findAllUnreadMessages(List aggregateList){
		int unreadCount = 0;
	    for (Iterator i = aggregateList.iterator(); i.hasNext();){
	      Object[] element = (Object[]) i.next();
	      /** filter on type and read status*/
	      if (Boolean.TRUE.equals(element[0])){
	        continue;
	      }
	      else{        
	        unreadCount += ((Integer) element[2]).intValue();
	      }      
	    }
	            
	    return unreadCount;    
	}
	
	public void resetAllUsersSynopticInfoInSite(String siteId){
		List<String> users = new ArrayList<String>();
		Site site;
		try {
			site = getSite(siteId);

			for (Iterator iterator = site.getMembers().iterator(); iterator.hasNext();) {
				Member member = (Member) iterator.next();
				String userId = member.getUserId();
				users.add(userId);
			}
			
			resetAllUsersSynopticInfoInSite(siteId, users);
			
		} catch (IdUnusedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void resetAllUsersSynopticInfoInSite(String siteId, List<String> users){
		String NEW_MESSAGE_COUNT_FOR_ALL_USERS_SQL = "SELECT USER_ID, count(*) unread_messages " + 
														"FROM MFR_PVT_MSG_USR_T message " +									
														"where READ_STATUS = 0 and CONTEXT_ID = ? " +
														"Group By USER_ID";
		
		String RETURN_ALL_FORUMS_AND_TOPICS_SQL = "select forum.ID as FORUM_ID, topic.ID as TOPIC_ID, forum.DRAFT as isForumDraft, topic.DRAFT as isTopicDraft, topic.MODERATED as isTopicModerated, forum.LOCKED as isForumLocked, topic.LOCKED as isTopicLocked, forum.CREATED_BY as forumCreatedBy, topic.CREATED_BY as topicCreatedBy, forum.AVAILABILITY as forumAvailability, topic.AVAILABILITY as topicAvailability  " +
														"from MFR_AREA_T area, MFR_OPEN_FORUM_T forum, MFR_TOPIC_T topic " + 
														"Where area.ID = forum.surrogateKey and forum.ID = topic.of_surrogateKey " +
														"and area.CONTEXT_ID = ?";
		Connection clConnection = null;  	
		//Statement statement = null;
		PreparedStatement newMessageCountForAllUsers = null;
		PreparedStatement returnAllForumsAndTopics = null;
		ResultSet forumsAndTopicsRS = null;
		ResultSet newMessagesCountRS = null;
		try {
			Site site = getSite(siteId);
			
			
			clConnection = SqlService.borrowConnection();
						
			//setup prepared statements:
			newMessageCountForAllUsers = clConnection.prepareStatement(NEW_MESSAGE_COUNT_FOR_ALL_USERS_SQL);
			newMessageCountForAllUsers.setString(1, siteId);
			returnAllForumsAndTopics = clConnection.prepareStatement(RETURN_ALL_FORUMS_AND_TOPICS_SQL);
			returnAllForumsAndTopics.setString(1, siteId);
			
			forumsAndTopicsRS = returnAllForumsAndTopics.executeQuery();			
			HashMap<Long, DecoratedForumInfo> dfHM = getDecoratedForumsAndTopics(forumsAndTopicsRS);
			
			newMessagesCountRS = newMessageCountForAllUsers.executeQuery();
			HashMap<String, Integer> unreadMessagesHM = getUnreadMessagesHM(newMessagesCountRS);
						
			for (Iterator iterator = users.iterator(); iterator.hasNext();) {
        		String userId = (String) iterator.next();        		        		
        		DecoratedCompiledMessageStats dcms = getDMessageStats(userId, siteId, site, dfHM, unreadMessagesHM);
           		createOrUpdateSynopticToolInfo(userId, siteId, dcms.getSiteName(), dcms.getUnreadPrivateAmt(), dcms.getUnreadForumsAmt());
			}
			
		} catch (IdUnusedException e) {
			LOG.error(e);
		} catch (SQLException e) {
			LOG.error(e);
		} finally{

			try {
				if(forumsAndTopicsRS != null)
					forumsAndTopicsRS.close();
			} catch (Exception e) {
				LOG.warn(e);
			}

			try {
				if(newMessagesCountRS != null)
					newMessagesCountRS.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			try {
				if(newMessageCountForAllUsers != null)
					newMessageCountForAllUsers.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			try {
				if(returnAllForumsAndTopics != null)
					returnAllForumsAndTopics.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			SqlService.returnConnection(clConnection);
		}
		
	}
	
	
	/**
	 * This method is used to get live information regarding the new message count per user for a forum ID
	 * 
	 * This information can be used to compare against a later current information set after an event takes place
	 * (ie. after saving a forum)  By only looking at the one forum that was updated, we can compare the two results
	 * and update the synoptic data based on the difference while avoiding calling unneeded forums, which can slow
	 * down this process significantly
	 * 
	 * @param siteId
	 * @param forumId
	 * @return
	 */
	public HashMap<String, Integer> getUserToNewMessagesForForumMap(String siteId, Long forumId, Long topicId){
		HashMap<String, Integer> returnHM = new HashMap<String, Integer>();
		String RETURN_ALL_TOPICS_FOR_FORUM_SQL = "select forum.ID as FORUM_ID, topic.ID as TOPIC_ID, forum.DRAFT as isForumDraft, topic.DRAFT as isTopicDraft, topic.MODERATED as isTopicModerated, forum.LOCKED as isForumLocked, topic.LOCKED as isTopicLocked, forum.CREATED_BY as forumCreatedBy, topic.CREATED_BY as topicCreatedBy, forum.AVAILABILITY as forumAvailability, topic.AVAILABILITY as topicAvailability  " +
													"from MFR_AREA_T area, MFR_OPEN_FORUM_T forum, MFR_TOPIC_T topic " + 
													"Where area.ID = forum.surrogateKey and forum.ID = topic.of_surrogateKey " +
													"and area.CONTEXT_ID = ? and forum.ID = ?";
		if(topicId != null){
			RETURN_ALL_TOPICS_FOR_FORUM_SQL = RETURN_ALL_TOPICS_FOR_FORUM_SQL + " and topic.ID = ?"; 
		}
		
		
		
		List<String> users = new ArrayList<String>();
		Site site;
		Connection clConnection = null;  	
		PreparedStatement returnAllTopicsForForum = null;
		ResultSet forumsAndTopicsRS = null;
		try {
			site = getSite(siteId);

			//get the list of users in the site:
			for (Iterator iterator = site.getMembers().iterator(); iterator.hasNext();) {
				Member member = (Member) iterator.next();
				String userId = member.getUserId();
				users.add(userId);
			}
			
			
			
			
			clConnection = SqlService.borrowConnection();
			returnAllTopicsForForum = clConnection.prepareStatement(RETURN_ALL_TOPICS_FOR_FORUM_SQL);
			returnAllTopicsForForum.setString(1, siteId);
			returnAllTopicsForForum.setString(2, "" +forumId);
			if(topicId != null)
				returnAllTopicsForForum.setString(3, "" +topicId);
			
			
			forumsAndTopicsRS = returnAllTopicsForForum.executeQuery();			
			HashMap<Long, DecoratedForumInfo> dfHM = getDecoratedForumsAndTopics(forumsAndTopicsRS);
			
			
			for (Iterator iterator = users.iterator(); iterator.hasNext();) {
        		String userId = (String) iterator.next();        		
        		//by passing a null, we can ignore all message tool calls (speeding up the process)
        		DecoratedCompiledMessageStats dcms = getDMessageStats(userId, siteId, site, dfHM, null);
        		returnHM.put(userId, Integer.valueOf(dcms.getUnreadForumsAmt()));
			}
						
		} catch (IdUnusedException e) {
			LOG.error(e);
		} catch (SQLException e) {
			LOG.error(e);
		} finally{
			try {
				if(forumsAndTopicsRS != null)
					forumsAndTopicsRS.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			try {
				if(returnAllTopicsForForum != null)
					returnAllTopicsForForum.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			
			SqlService.returnConnection(clConnection);
		}
		
		return returnHM;
	}
	
	public void updateSynopticMessagesForForumComparingOldMessagesCount(String siteId, Long forumId, Long topicId, HashMap<String, Integer> previousCountHM){
		if(previousCountHM != null){

			// get new count Hash Map for comparison
			HashMap<String, Integer> newCountHM = getUserToNewMessagesForForumMap(siteId, forumId, topicId);

			if(newCountHM != null){
				//loop through new count HM and compare:
				Set<String> users = newCountHM.keySet();


				int oldForumCount = 0;
				int newForumCount = 0;
				int forumCountDiff = 0;

				for (Iterator iterator = users.iterator(); iterator.hasNext();) {
					String userId = (String) iterator.next();

					oldForumCount = 0;
					newForumCount = 0;
					forumCountDiff = 0;

					Integer oldForumCountInt = previousCountHM.get(userId);
					if(oldForumCountInt != null){
						oldForumCount = oldForumCountInt.intValue();
					}	

					Integer newForumCountInt = newCountHM.get(userId);
					if(newForumCountInt != null){
						newForumCount = newForumCountInt.intValue();
					}

					forumCountDiff = newForumCount - oldForumCount;

					this.updateDifferenceForumSynopticInfoHelper(userId, siteId, forumCountDiff);
				}
			}
		}
	}
	
	
	private DecoratedCompiledMessageStats getDMessageStats(String userId, String siteId, Site site, HashMap<Long, DecoratedForumInfo> dfHM, HashMap<String, Integer> unreadMessagesHM){
		
		final DecoratedCompiledMessageStats dcms = new DecoratedCompiledMessageStats();

		// Check if tool within site
		// if so, get stats for just this site

		boolean isMessageForumsPageInSite = isMessageForumsPageInSite(site);
		dcms.setSiteName(site.getTitle());
		dcms.setSiteId(siteId);
		
		//MSGCNTR-430 if this is the anon user we can't actualy do anything more -DH
		if (userId == null) {
			return dcms;
		}
		
		if (isMessageForumsPageInSite || isMessagesPageInSite(site)) 
		{
			if(unreadMessagesHM != null){

				// Get private message area so we can get the private message forum so we can get the
				// List of topics so we can get the Received topic to finally determine number of unread messages
				// only check if Messages & Forums in site, just Messages is on by default
				boolean isEnabled;



				if (isMessageForumsPageInSite) {
					final Area area = pvtMessageManager.getPrivateMessageArea(siteId);
					isEnabled = area.getEnabled().booleanValue();
				}
				else {
					isEnabled = true;
				}

				if (isEnabled) {
					Integer newMessageCount = unreadMessagesHM.get(userId);
					if(newMessageCount != null){
						dcms.setUnreadPrivateAmt(newMessageCount.intValue());
					}								
				}
			}
		}

		if (isMessageForumsPageInSite || isForumsPageInSite(site)) 
		{
			Set<Long> dfKeySet = null;
			int unreadForum = 0;
			

			if(dfHM != null){
				boolean isSuperUser = SecurityService.isSuperUser(userId);
				//site has forums added to the tool
				dfKeySet = dfHM.keySet();

				boolean isInstructor = getForumManager().isInstructor(userId, "/site/" + siteId);
				
				boolean hasOverridingPermission = false;
				if(isInstructor
						|| isSuperUser){
					hasOverridingPermission = true;
				}
				boolean isAreaAvailable = true;
				if(!hasOverridingPermission){
					//need to check that the area hasn't been disabled:
					Area area = forumManager.getDiscussionForumArea(siteId);
					if(area != null){
						isAreaAvailable = area.getAvailability();
					}
				}
					
				if(isAreaAvailable){
					for (Iterator iterator = dfKeySet.iterator(); iterator.hasNext();) {
						Long dfId = (Long) iterator.next();

						DecoratedForumInfo dForum = dfHM.get(dfId);



						// Only count unread messages for forums the user can view:
						if ((dForum.getIsDraft().equals(Boolean.FALSE) && dForum.getAvailability()) ||
								hasOverridingPermission ||
								forumManager.isForumOwner(dfId, dForum.getCreator(), userId, "/site/" + siteId))
						{ 

							final Iterator<DecoratedTopicsInfo> topicIter = dForum.getTopics().iterator();

							while (topicIter.hasNext()) 
							{
								DecoratedTopicsInfo topic = (DecoratedTopicsInfo) topicIter.next();

								Long topicId = topic.getTopicId();
								Boolean isTopicDraft = topic.getIsDraft();
								Boolean isTopicModerated = topic.getIsModerated();
								Boolean isTopicLocked = topic.getIsLocked();
								String topicOwner = topic.getCreator();

								//Only count unread messages for topics the user can view:
								if ((isTopicDraft.equals(Boolean.FALSE) && topic.getAvailability())
										|| isInstructor
										|| isSuperUser
										||forumManager.isTopicOwner(topicId, topicOwner, userId, "/site/" + siteId)){ 

									if (getUiPermissionsManager().isRead(topicId, isTopicDraft, dForum.getIsDraft(), userId, siteId))
									{
										if (!isTopicModerated.booleanValue() || (isTopicModerated.booleanValue() && 
												getUiPermissionsManager().isModeratePostings(topicId, dForum.getIsLocked(), dForum.getIsDraft(), isTopicLocked, isTopicDraft, userId, siteId)))
										{
											unreadForum += getMessageManager().findUnreadMessageCountByTopicIdByUserId(topicId, userId);
										}
										else
										{	
											// b/c topic is moderated and user does not have mod perm, user may only
											// see approved msgs or pending/denied msgs authored by user
											unreadForum += getMessageManager().findUnreadViewableMessageCountByTopicIdByUserId(topicId, userId);

										}
									}
								}
							}
						}
					}
				}
			}

			dcms.setUnreadForumsAmt(unreadForum);
		}


		return dcms;
	}
	
	
	/**
	 * Returns List to populate page if on Home page of a site
	 * 
	 * @return
	 * 		List of DecoratedCompiledMessageStats for a particular site
	 */
	private DecoratedCompiledMessageStats getSiteContents(String siteId, String userId) 
	{
		String NEW_MESSAGE_COUNT_SQL = "SELECT USER_ID, count(*) unread_messages " +
										"FROM MFR_PVT_MSG_USR_T message " +									
										"where READ_STATUS = 0 and USER_ID = ? and CONTEXT_ID = ? " +
										"Group By USER_ID";
		
		String RETURN_ALL_FORUMS_AND_TOPICS_SQL = "select forum.ID as FORUM_ID, topic.ID as TOPIC_ID, forum.DRAFT as isForumDraft, topic.DRAFT as isTopicDraft, topic.MODERATED as isTopicModerated, forum.LOCKED as isForumLocked, topic.LOCKED as isTopicLocked, forum.CREATED_BY as forumCreatedBy, topic.CREATED_BY as topicCreatedBy, forum.AVAILABILITY as forumAvailability, topic.AVAILABILITY as topicAvailability  " +
													"from MFR_AREA_T area, MFR_OPEN_FORUM_T forum, MFR_TOPIC_T topic " + 
													"Where area.ID = forum.surrogateKey and forum.ID = topic.of_surrogateKey " +
													"and area.CONTEXT_ID = ?";
		
		Connection clConnection = null;  	
		PreparedStatement newMessageCount = null;
		PreparedStatement returnAllForumsAndTopics = null;
		ResultSet forumsAndTopicsRS = null;
		ResultSet newMessagesCountRS = null;
		
		
		final DecoratedCompiledMessageStats dcms = new DecoratedCompiledMessageStats();

		try{
			clConnection = SqlService.borrowConnection();
			newMessageCount = clConnection.prepareStatement(NEW_MESSAGE_COUNT_SQL);
			newMessageCount.setString(1, userId);
			newMessageCount.setString(2, siteId);
			returnAllForumsAndTopics = clConnection.prepareStatement(RETURN_ALL_FORUMS_AND_TOPICS_SQL);			
			returnAllForumsAndTopics.setString(1, siteId);
			
			Site site = getSite(siteId);
			
			forumsAndTopicsRS = returnAllForumsAndTopics.executeQuery();			
			HashMap<Long, DecoratedForumInfo> dfHM = getDecoratedForumsAndTopics(forumsAndTopicsRS);
			
			newMessagesCountRS = newMessageCount.executeQuery();
			HashMap<String, Integer> unreadMessagesHM = getUnreadMessagesHM(newMessagesCountRS);
						
			return getDMessageStats(userId, siteId, site, dfHM, unreadMessagesHM);
			
		}catch(IdUnusedException e) {
			LOG.error("IdUnusedException while trying to check if site has MF tool.");
		} catch (SQLException e) {
			LOG.error(e);
		} finally{
			
			try {
				if(forumsAndTopicsRS != null)
					forumsAndTopicsRS.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			
			try {
				if(newMessagesCountRS != null)
					newMessagesCountRS.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			
			try {
				if(returnAllForumsAndTopics != null)
					returnAllForumsAndTopics.close();
			} catch (Exception e) {
				LOG.warn(e);
			}	
			
			try {
				if(newMessageCount != null)
					newMessageCount.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			
			SqlService.returnConnection(clConnection);
		}
		
		return dcms;
	}
	
	
	private HashMap<Long, DecoratedForumInfo> getDecoratedForumsAndTopics(ResultSet rs){
		HashMap<Long, DecoratedForumInfo> returnHM = new HashMap<Long, DecoratedForumInfo>();

		try {
			String FORUM_CREATED_BY, TOPIC_CREATED_BY;
			Long FORUM_ID, TOPIC_ID;
			Boolean IS_TOPIC_DRAFT, IS_FORUM_DRAFT, IS_TOPIC_MODERATED, IS_FORUM_LOCKED, IS_TOPIC_LOCKED, FORUM_AVAILABILITY, TOPIC_AVAILABILITY;

			while(rs.next()){
				FORUM_ID = rs.getLong("FORUM_ID");
				TOPIC_ID = rs.getLong("TOPIC_ID");
				IS_TOPIC_DRAFT = rs.getBoolean("isTopicDraft");
				IS_FORUM_DRAFT = rs.getBoolean("isForumDraft");
				IS_TOPIC_MODERATED = rs.getBoolean("isTopicModerated");
				IS_FORUM_LOCKED = rs.getBoolean("isForumLocked");
				IS_TOPIC_LOCKED = rs.getBoolean("isTopicLocked");
				FORUM_CREATED_BY = rs.getString("forumCreatedBy");
				TOPIC_CREATED_BY = rs.getString("topicCreatedBy");
				FORUM_AVAILABILITY = rs.getBoolean("forumAvailability");
				TOPIC_AVAILABILITY = rs.getBoolean("topicAvailability");


				//hashmap already has this site id, now look for forum id:
				if(returnHM.containsKey(FORUM_ID)){						
					DecoratedTopicsInfo dTopic = new DecoratedTopicsInfo(TOPIC_ID, IS_TOPIC_LOCKED, IS_TOPIC_DRAFT, TOPIC_AVAILABILITY, IS_TOPIC_MODERATED, TOPIC_CREATED_BY);
					returnHM.get(FORUM_ID).addTopic(dTopic);
				}else{
					//this is a new forum, so add it to the list						
					DecoratedTopicsInfo dTopic = new DecoratedTopicsInfo(TOPIC_ID, IS_TOPIC_LOCKED, IS_TOPIC_DRAFT, TOPIC_AVAILABILITY, IS_TOPIC_MODERATED, TOPIC_CREATED_BY);
					DecoratedForumInfo dForum = new DecoratedForumInfo(FORUM_ID, IS_FORUM_LOCKED, IS_FORUM_DRAFT, FORUM_AVAILABILITY, FORUM_CREATED_BY);
					dForum.addTopic(dTopic);

					returnHM.put(FORUM_ID, dForum);
				}												
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return returnHM;
	}
	
	public HashMap<String, Integer> getUnreadMessagesHM(ResultSet rs){
		HashMap<String, Integer> returnHM = new HashMap<String, Integer>();
		
		if(rs != null){
			try{
				String userId;
				Integer messageCount;
			while(rs.next()){
				userId = rs.getString("USER_ID");
				messageCount = Integer.valueOf(rs.getInt("unread_messages"));

				returnHM.put(userId, messageCount);		
			}
			}catch(Exception e){
				LOG.error(e);
			}
		}
		
		return returnHM;
	}

	/**
	 * @return TRUE if Messages & Forums (Message Center) exists in this site,
	 *         FALSE otherwise
	 */
	private boolean isMessageForumsPageInSite(Site thisSite) {
		if (mfPageInSiteMap == null) {
			mfPageInSiteMap = new HashMap();
		}
		
		Boolean isMFPageInSite;
		if ((isMFPageInSite = (Boolean) mfPageInSiteMap.get(thisSite)) == null) {
			isMFPageInSite = isToolInSite(thisSite, DiscussionForumService.MESSAGE_CENTER_ID);
			mfPageInSiteMap.put(thisSite, isMFPageInSite);
		}
		
		return isMFPageInSite;
	}
	
	/**
	 * Return TRUE if tool with id passed in exists in site passed in
	 * FALSE otherwise.
	 * 
	 * @param thisSite
	 * 			Site object to check
	 * @param toolId
	 * 			Tool id to be checked
	 * 
	 * @return
	 */
	private boolean isToolInSite(Site thisSite, String toolId) {
		final Collection toolsInSite = thisSite.getTools(toolId);

		return ! toolsInSite.isEmpty();		
	}

	
	/**
	 * Returns the Site object for this id, if it exists.
	 * If not, returns IdUnusedException
	 * 
	 * @param siteId
	 * 			The site id to check
	 * 
	 * @return
	 * 			Site object for this id
	 */
	private Site getSite(String siteId) 
	throws IdUnusedException {
		if (sitesMap == null) {
			sitesMap = new HashMap();
		}
	
		if (sitesMap.get(siteId) == null) {
			Site site = SiteService.getSite(siteId);
			sitesMap.put(site.getId(), site);
			return site;
		}
		else {
			return (Site) sitesMap.get(siteId);
		}
	}

	
	/**
	 * @return TRUE if Messages tool exists in this site,
	 *         FALSE otherwise
	 */
	private boolean isMessagesPageInSite(Site thisSite) {
		return isToolInSite(thisSite, DiscussionForumService.MESSAGES_TOOL_ID);
	}
	
	/**
	 * @return TRUE if Forums tool exists in this site,
	 *         FALSE otherwise
	 */
	private boolean isForumsPageInSite(Site thisSite) {
		return isToolInSite(thisSite, DiscussionForumService.FORUMS_TOOL_ID);
	}
	
	
	public MessageForumsMessageManager getMessageManager() {
		return messageManager;
	}

	public void setMessageManager(MessageForumsMessageManager messageManager) {
		this.messageManager = messageManager;
	}
	
	public UIPermissionsManager getUiPermissionsManager() {
		return uiPermissionsManager;
	}

	public void setUiPermissionsManager(UIPermissionsManager uiPermissionsManager) {
		this.uiPermissionsManager = uiPermissionsManager;
	}
	
	public PrivateMessageManager getPvtMessageManager() {
		return pvtMessageManager;
	}

	public void setPvtMessageManager(PrivateMessageManager pvtMessageManager) {
		this.pvtMessageManager = pvtMessageManager;
	}

	public MessageForumsTypeManager getTypeManager() {
		return typeManager;
	}

	public void setTypeManager(MessageForumsTypeManager typeManager) {
		this.typeManager = typeManager;
	}
	
	public DiscussionForumManager getForumManager() {
		return forumManager;
	}

	public void setForumManager(DiscussionForumManager forumManager) {
		this.forumManager = forumManager;
	}
	
	/**
	 * Used to store synoptic information for a users unread messages.
	 * Whether on the Home page of a site or in MyWorkspace determines
	 * what properties are filled.
	 * <p>
	 * If in MyWorkspace, each object contains the number of unread
	 * Private Messages and number of unread Discussion Forum messages.
	 * </p>
	 * <p>
	 * If in the Home page of a site, each object contains either the
	 * number of unread Private Messages or number of unread Discussion 
	 * Forum messages.</p>
	 * 
	 * @author josephrodriguez
	 *
	 */
	public class DecoratedCompiledMessageStats {
		private String siteName;
		private String siteId;
		
		/** MyWorkspace information */
		private int unreadPrivateAmt = 0;
		private int unreadForumsAmt = 0;
		private String mcPageURL;
		private String privateMessagesUrl;
		private boolean messagesandForums;
		private boolean messages;
		private boolean forums;
		
		public String getSiteName() {
			return siteName;
		}

		public void setSiteName(String siteName) {
			this.siteName = siteName;
		}

		public int getUnreadPrivateAmt() {
			return unreadPrivateAmt;
		}

		public void setUnreadPrivateAmt(int unreadPrivateAmt) {
			this.unreadPrivateAmt = unreadPrivateAmt;
		}

		public int getUnreadForumsAmt() {
			return unreadForumsAmt;
		}

		public void setUnreadForumsAmt(int unreadForumsAmt) {
			this.unreadForumsAmt = unreadForumsAmt;
		}

		public String getMcPageURL() {
			return mcPageURL;
		}

		public void setMcPageURL(String mcPageURL) {
			this.mcPageURL = mcPageURL;
		}

		public String getSiteId() {
			return siteId;
		}

		public void setSiteId(String siteId) {
			this.siteId = siteId;
		}

		public String getPrivateMessagesUrl() {
			return privateMessagesUrl;
		}

		public void setPrivateMessagesUrl(String privateMessagesUrl) {
			this.privateMessagesUrl = privateMessagesUrl;
		}

		public boolean isMessagesandForums() {
			return messagesandForums;
		}

		public void setMessagesandForums(boolean messagesandForums) {
			this.messagesandForums = messagesandForums;
		}

		public boolean isMessages() {
			return messages;
		}

		public void setMessages(boolean messages) {
			this.messages = messages;
		}

		public boolean isForums() {
			return forums;
		}

		public void setForums(boolean forums) {
			this.forums = forums;
		}
	}
	
public class DecoratedForumInfo{
		
		private Long forumId;
		private Boolean isLocked, isDraft, availability;
		private String creator;
		private ArrayList<DecoratedTopicsInfo> topics = new ArrayList<DecoratedTopicsInfo>();
		
		public DecoratedForumInfo(Long forumId, Boolean isLocked, Boolean isDraft, Boolean availability, String creator){
			this.forumId = forumId;
			this.isLocked = isLocked;
			this.isDraft = isDraft;
			this.creator = creator;
			this.availability = availability;
		}

		public Long getForumId() {
			return forumId;
		}

		public void setForumId(Long forumId) {
			this.forumId = forumId;
		}

		public Boolean getIsLocked() {
			return isLocked;
		}

		public void setIsLocked(Boolean isLocked) {
			this.isLocked = isLocked;
		}

		public Boolean getIsDraft() {
			return isDraft;
		}

		public void setIsDraft(Boolean isDraft) {
			this.isDraft = isDraft;
		}

		public String getCreator() {
			return creator;
		}

		public void setCreator(String creator) {
			this.creator = creator;
		}

		public void addTopic(DecoratedTopicsInfo dTopics){
			topics.add(dTopics);
		}
		
		public ArrayList<DecoratedTopicsInfo> getTopics(){
			return topics;
		}

		public Boolean getAvailability() {
			return availability;
		}

		public void setAvailability(Boolean availability) {
			this.availability = availability;
		}
	}

	public class DecoratedTopicsInfo{
		
		private Long topicId;
		private Boolean isLocked, isDraft, isModerated, availability;
		private String creator;
		
		public DecoratedTopicsInfo(Long topicId, Boolean isLocked, Boolean isDraft, Boolean availability, Boolean isModerated, String creator){
			this.topicId = topicId;
			this.isLocked = isLocked;
			this.isDraft = isDraft;
			this.isModerated = isModerated;
			this.creator = creator;
			this.availability = availability;
		}

		public Long getTopicId() {
			return topicId;
		}

		public void setTopicId(Long topicId) {
			this.topicId = topicId;
		}

		public Boolean getIsLocked() {
			return isLocked;
		}

		public void setIsLocked(Boolean isLocked) {
			this.isLocked = isLocked;
		}

		public Boolean getIsDraft() {
			return isDraft;
		}

		public void setIsDraft(Boolean isDraft) {
			this.isDraft = isDraft;
		}

		public Boolean getIsModerated() {
			return isModerated;
		}

		public void setIsModerated(Boolean isModerated) {
			this.isModerated = isModerated;
		}

		public String getCreator() {
			return creator;
		}

		public void setCreator(String creator) {
			this.creator = creator;
		}

		public Boolean getAvailability() {
			return availability;
		}

		public void setAvailability(Boolean availability) {
			this.availability = availability;
		}
	}

	public void updateAllSiteTitles(final String siteId, final String siteTitle) {
		HibernateCallback hcb = new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query q = session.getNamedQuery(QUERY_UPDATE_ALL_SITE_TITLES);
				q.setParameter("siteTitle", siteTitle, Hibernate.STRING);
				q.setParameter("siteId", siteId, Hibernate.STRING);
				return q.executeUpdate();
			}
		};

		getHibernateTemplate().execute(hcb);
	}
}
<commit_msg>KNL-430 fix minor comment typo<commit_after>package org.sakaiproject.component.app.messageforums;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.sakaiproject.api.app.messageforums.Area;
import org.sakaiproject.api.app.messageforums.DiscussionForumService;
import org.sakaiproject.api.app.messageforums.MessageForumsMessageManager;
import org.sakaiproject.api.app.messageforums.MessageForumsTypeManager;
import org.sakaiproject.api.app.messageforums.SynopticMsgcntrItem;
import org.sakaiproject.api.app.messageforums.SynopticMsgcntrManager;
import org.sakaiproject.api.app.messageforums.ui.DiscussionForumManager;
import org.sakaiproject.api.app.messageforums.ui.PrivateMessageManager;
import org.sakaiproject.api.app.messageforums.ui.UIPermissionsManager;
import org.sakaiproject.authz.api.Member;
import org.sakaiproject.authz.cover.SecurityService;
import org.sakaiproject.component.app.messageforums.dao.hibernate.SynopticMsgcntrItemImpl;
import org.sakaiproject.db.cover.SqlService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.cover.SiteService;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class SynopticMsgcntrManagerImpl extends HibernateDaoSupport implements SynopticMsgcntrManager {
	
	private static final Log LOG = LogFactory.getLog(SynopticMsgcntrManagerImpl.class);
	private static final String QUERY_WORKSPACE_SYNOPTIC_ITEMS = "findWorkspaceSynopticMsgcntrItems";
	private static final String QUERY_SITE_SYNOPTIC_ITEMS = "findSiteSynopticMsgcntrItems";
	private static final String QUERY_UPDATE_ALL_SITE_TITLES = "updateSiteTitles";

	private HashMap mfPageInSiteMap, sitesMap;
	// transient variable for when on home page of site
	private transient DecoratedCompiledMessageStats siteContents;
	private MessageForumsMessageManager messageManager;
	private UIPermissionsManager uiPermissionsManager;
	private PrivateMessageManager pvtMessageManager;
	private MessageForumsTypeManager typeManager;
	private DiscussionForumManager forumManager;
	
	

	
	public SynopticMsgcntrManagerImpl() {}
	
	public void init() {
		LOG.info("init()");
	}

	public List<SynopticMsgcntrItem> getWorkspaceSynopticMsgcntrItems(final String userId) {

		HibernateCallback hcb = new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query q = session.getNamedQuery(QUERY_WORKSPACE_SYNOPTIC_ITEMS);
				q.setParameter("userId", userId, Hibernate.STRING);
				return q.list();
			}
		};

		return (List<SynopticMsgcntrItem>) getHibernateTemplate().execute(hcb);	  
	}

	public SynopticMsgcntrItem getSiteSynopticMsgcntrItem(final String userId, final String siteId) {

		HibernateCallback hcb = new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query q = session.getNamedQuery(QUERY_SITE_SYNOPTIC_ITEMS);
				q.setParameter("userId", userId, Hibernate.STRING);
				q.setParameter("siteId", siteId, Hibernate.STRING);
				return q.uniqueResult();
			}
		};

		return (SynopticMsgcntrItem) getHibernateTemplate().execute(hcb);	  
	}

	public SynopticMsgcntrItem createSynopticMsgcntrItem(String userId, String siteId, String siteTitle){
		return new SynopticMsgcntrItemImpl(userId, siteId, siteTitle);
	}

	public void saveSynopticMsgcntrItem(SynopticMsgcntrItem item){
		getHibernateTemplate().saveOrUpdate(item);
	}
	
	public void deleteSynopticMsgcntrItem(SynopticMsgcntrItem item){
		getHibernateTemplate().delete(item);
	}
	
	public void incrementMessagesSynopticToolInfo(String userId, String siteId){
		incrementSynopticToolInfo(userId, siteId, true);
	}
	
	public void incrementForumSynopticToolInfo(String userId, String siteId){
		incrementSynopticToolInfo(userId, siteId, false);
	}
	
	private void incrementSynopticToolInfo(String userId, String siteId, boolean messages){
		  SynopticMsgcntrItem item = getSiteSynopticMsgcntrItem(userId, siteId);
		  if(item == null){
			  //item does not exist, call the reset function to set the 
			  //actually number of unread messages instead of incrementing
			 resetMessagesAndForumSynopticInfo(userId, siteId);
		  }else{
			  if(messages)
				  item.incrementNewMessagesCount();
			  else
				  item.incrementNewForumCount();
			  saveSynopticMsgcntrItem(item);
		  }
	}
	
	public void decrementMessagesSynopticToolInfo(String userId, String siteId){
		decrementSynopticToolInfo(userId, siteId, true);
	}
	
	public void decrementForumSynopticToolInfo(String userId, String siteId){
		decrementSynopticToolInfo(userId, siteId, false);
	}
	
	private void decrementSynopticToolInfo(String userId, String siteId, boolean messages){
		  SynopticMsgcntrItem item = getSiteSynopticMsgcntrItem(userId, siteId);
		  if(item == null){
			  //item does not exist, call the reset function to set the 
			  //actually number of unread messages instead of decrementing
			  resetMessagesAndForumSynopticInfo(userId, siteId);
		  }else{
			  if(messages)
				  item.decrementNewMessagesCount();
			  else
				  item.decrementNewForumCount();
			  saveSynopticMsgcntrItem(item);
		  }		 
	}
	
	
	public void resetMessagesAndForumSynopticInfo(String userId, String siteId) {

		DecoratedCompiledMessageStats dcmStats = this.getSiteInfo(siteId,
				userId);

		SynopticMsgcntrItem item = getSiteSynopticMsgcntrItem(userId, siteId);
		if (item == null) {
			SynopticMsgcntrItem synopticMsgcntrItem = createSynopticMsgcntrItem(
					userId, siteId, dcmStats.getSiteName());
			synopticMsgcntrItem.setNewMessagesCount(dcmStats
					.getUnreadPrivateAmt());
			synopticMsgcntrItem.setNewForumCount(dcmStats.getUnreadForumsAmt());

			saveSynopticMsgcntrItem(synopticMsgcntrItem);
		} else {
			item.setNewMessagesCount(dcmStats.getUnreadPrivateAmt());
			item.setMessagesLastVisitToCurrentDt();

			item.setNewForumCount(dcmStats.getUnreadForumsAmt());
			item.setForumLastVisitToCurrentDt();

			saveSynopticMsgcntrItem(item);
		}
	}

	public void setMessagesSynopticInfoHelper(String userId, String siteId, int newMessageCount){
		setSynopticInfoHelper(userId, siteId, true, newMessageCount);
	}
	
	public void setForumSynopticInfoHelper(String userId, String siteId, int newMessageCount){
		setSynopticInfoHelper(userId, siteId, false, newMessageCount);
	}
	
	private void setSynopticInfoHelper(String userId, String siteId, boolean messages, int newMessageCount){
		//this could be an anon access
		if (userId == null && forumManager.getAnonRole()) {
			return;
		}
		
		SynopticMsgcntrItem item = getSiteSynopticMsgcntrItem(userId, siteId);
		if(item == null){
			//item does not exist, call the reset function to set the 
			//actually number of unread messages instead of decrementing
			resetMessagesAndForumSynopticInfo(userId, siteId);
		}else{
			if(messages){
				item.setNewMessagesCount(newMessageCount);				
				item.setMessagesLastVisitToCurrentDt();
			}else{
				item.setNewForumCount(newMessageCount);
				item.setForumLastVisitToCurrentDt();
			}
			saveSynopticMsgcntrItem(item);
		}
	}
	
	/*
	 * Update Difference will get the existing count and add the difference (if negative, then its a subtract mathamatically)
	 */
	
	public void updateDifferenceMessagesSynopticInfoHelper(String userId, String siteId, int differenceCount){
		updateDifferenceSynopticInfoHelper(userId, siteId, true, differenceCount);
	}
	
	public void updateDifferenceForumSynopticInfoHelper(String userId, String siteId, int differenceCount){
		updateDifferenceSynopticInfoHelper(userId, siteId, false, differenceCount);
	}
	
	private void updateDifferenceSynopticInfoHelper(String userId, String siteId, boolean messages, int differenceCount){
		SynopticMsgcntrItem item = getSiteSynopticMsgcntrItem(userId, siteId);
		if(item == null){
			//item does not exist, call the reset function to set the 
			//actually number of unread messages instead of decrementing
			resetMessagesAndForumSynopticInfo(userId, siteId);
		}else{
			if(messages){
				int newCount = item.getNewMessagesCount() + differenceCount;
				if(newCount < 0){
					newCount = 0;
				}
				item.setNewMessagesCount(newCount);				
				item.setMessagesLastVisitToCurrentDt();
			}else{
				int newCount = item.getNewForumCount() + differenceCount;
				if(newCount < 0){
					newCount = 0;
				}
				item.setNewForumCount(newCount);
				item.setForumLastVisitToCurrentDt();
			}
			saveSynopticMsgcntrItem(item);
		}
	}
	
	
	public void createOrUpdateSynopticToolInfo(String userId, String siteId, String siteTitle, int unreadMessageCount, int unreadForumCount){	
		SynopticMsgcntrItem item = getSiteSynopticMsgcntrItem(userId, siteId);
		 if(item == null){
			 SynopticMsgcntrItem synopticMsgcntrItem = createSynopticMsgcntrItem(userId, siteId, siteTitle);	
			 synopticMsgcntrItem.setNewMessagesCount(unreadMessageCount);
			 synopticMsgcntrItem.setNewForumCount(unreadForumCount);

			 saveSynopticMsgcntrItem(synopticMsgcntrItem);								
		 }else{
			 item.setNewMessagesCount(unreadMessageCount);				
			 item.setMessagesLastVisitToCurrentDt();

			 item.setNewForumCount(unreadForumCount);
			 item.setForumLastVisitToCurrentDt();
			 saveSynopticMsgcntrItem(item);
			 if(item.getSiteTitle() == null || (item.getSiteTitle() != null && !item.getSiteTitle().equals(siteTitle))){
				 updateAllSiteTitles(siteId, siteTitle);
			 }
		 }
	}
	
	
	
	/**
	 * @return 
	 * 		DecoratedCompiledMessageStats for a single site
	 */
	public DecoratedCompiledMessageStats getSiteInfo(String siteId, String userId) {
		return getSiteContents(siteId, userId);
	}
	
	public int findAllUnreadMessages(List aggregateList){
		int unreadCount = 0;
	    for (Iterator i = aggregateList.iterator(); i.hasNext();){
	      Object[] element = (Object[]) i.next();
	      /** filter on type and read status*/
	      if (Boolean.TRUE.equals(element[0])){
	        continue;
	      }
	      else{        
	        unreadCount += ((Integer) element[2]).intValue();
	      }      
	    }
	            
	    return unreadCount;    
	}
	
	public void resetAllUsersSynopticInfoInSite(String siteId){
		List<String> users = new ArrayList<String>();
		Site site;
		try {
			site = getSite(siteId);

			for (Iterator iterator = site.getMembers().iterator(); iterator.hasNext();) {
				Member member = (Member) iterator.next();
				String userId = member.getUserId();
				users.add(userId);
			}
			
			resetAllUsersSynopticInfoInSite(siteId, users);
			
		} catch (IdUnusedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void resetAllUsersSynopticInfoInSite(String siteId, List<String> users){
		String NEW_MESSAGE_COUNT_FOR_ALL_USERS_SQL = "SELECT USER_ID, count(*) unread_messages " + 
														"FROM MFR_PVT_MSG_USR_T message " +									
														"where READ_STATUS = 0 and CONTEXT_ID = ? " +
														"Group By USER_ID";
		
		String RETURN_ALL_FORUMS_AND_TOPICS_SQL = "select forum.ID as FORUM_ID, topic.ID as TOPIC_ID, forum.DRAFT as isForumDraft, topic.DRAFT as isTopicDraft, topic.MODERATED as isTopicModerated, forum.LOCKED as isForumLocked, topic.LOCKED as isTopicLocked, forum.CREATED_BY as forumCreatedBy, topic.CREATED_BY as topicCreatedBy, forum.AVAILABILITY as forumAvailability, topic.AVAILABILITY as topicAvailability  " +
														"from MFR_AREA_T area, MFR_OPEN_FORUM_T forum, MFR_TOPIC_T topic " + 
														"Where area.ID = forum.surrogateKey and forum.ID = topic.of_surrogateKey " +
														"and area.CONTEXT_ID = ?";
		Connection clConnection = null;  	
		//Statement statement = null;
		PreparedStatement newMessageCountForAllUsers = null;
		PreparedStatement returnAllForumsAndTopics = null;
		ResultSet forumsAndTopicsRS = null;
		ResultSet newMessagesCountRS = null;
		try {
			Site site = getSite(siteId);
			
			
			clConnection = SqlService.borrowConnection();
						
			//setup prepared statements:
			newMessageCountForAllUsers = clConnection.prepareStatement(NEW_MESSAGE_COUNT_FOR_ALL_USERS_SQL);
			newMessageCountForAllUsers.setString(1, siteId);
			returnAllForumsAndTopics = clConnection.prepareStatement(RETURN_ALL_FORUMS_AND_TOPICS_SQL);
			returnAllForumsAndTopics.setString(1, siteId);
			
			forumsAndTopicsRS = returnAllForumsAndTopics.executeQuery();			
			HashMap<Long, DecoratedForumInfo> dfHM = getDecoratedForumsAndTopics(forumsAndTopicsRS);
			
			newMessagesCountRS = newMessageCountForAllUsers.executeQuery();
			HashMap<String, Integer> unreadMessagesHM = getUnreadMessagesHM(newMessagesCountRS);
						
			for (Iterator iterator = users.iterator(); iterator.hasNext();) {
        		String userId = (String) iterator.next();        		        		
        		DecoratedCompiledMessageStats dcms = getDMessageStats(userId, siteId, site, dfHM, unreadMessagesHM);
           		createOrUpdateSynopticToolInfo(userId, siteId, dcms.getSiteName(), dcms.getUnreadPrivateAmt(), dcms.getUnreadForumsAmt());
			}
			
		} catch (IdUnusedException e) {
			LOG.error(e);
		} catch (SQLException e) {
			LOG.error(e);
		} finally{

			try {
				if(forumsAndTopicsRS != null)
					forumsAndTopicsRS.close();
			} catch (Exception e) {
				LOG.warn(e);
			}

			try {
				if(newMessagesCountRS != null)
					newMessagesCountRS.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			try {
				if(newMessageCountForAllUsers != null)
					newMessageCountForAllUsers.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			try {
				if(returnAllForumsAndTopics != null)
					returnAllForumsAndTopics.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			SqlService.returnConnection(clConnection);
		}
		
	}
	
	
	/**
	 * This method is used to get live information regarding the new message count per user for a forum ID
	 * 
	 * This information can be used to compare against a later current information set after an event takes place
	 * (ie. after saving a forum)  By only looking at the one forum that was updated, we can compare the two results
	 * and update the synoptic data based on the difference while avoiding calling unneeded forums, which can slow
	 * down this process significantly
	 * 
	 * @param siteId
	 * @param forumId
	 * @return
	 */
	public HashMap<String, Integer> getUserToNewMessagesForForumMap(String siteId, Long forumId, Long topicId){
		HashMap<String, Integer> returnHM = new HashMap<String, Integer>();
		String RETURN_ALL_TOPICS_FOR_FORUM_SQL = "select forum.ID as FORUM_ID, topic.ID as TOPIC_ID, forum.DRAFT as isForumDraft, topic.DRAFT as isTopicDraft, topic.MODERATED as isTopicModerated, forum.LOCKED as isForumLocked, topic.LOCKED as isTopicLocked, forum.CREATED_BY as forumCreatedBy, topic.CREATED_BY as topicCreatedBy, forum.AVAILABILITY as forumAvailability, topic.AVAILABILITY as topicAvailability  " +
													"from MFR_AREA_T area, MFR_OPEN_FORUM_T forum, MFR_TOPIC_T topic " + 
													"Where area.ID = forum.surrogateKey and forum.ID = topic.of_surrogateKey " +
													"and area.CONTEXT_ID = ? and forum.ID = ?";
		if(topicId != null){
			RETURN_ALL_TOPICS_FOR_FORUM_SQL = RETURN_ALL_TOPICS_FOR_FORUM_SQL + " and topic.ID = ?"; 
		}
		
		
		
		List<String> users = new ArrayList<String>();
		Site site;
		Connection clConnection = null;  	
		PreparedStatement returnAllTopicsForForum = null;
		ResultSet forumsAndTopicsRS = null;
		try {
			site = getSite(siteId);

			//get the list of users in the site:
			for (Iterator iterator = site.getMembers().iterator(); iterator.hasNext();) {
				Member member = (Member) iterator.next();
				String userId = member.getUserId();
				users.add(userId);
			}
			
			
			
			
			clConnection = SqlService.borrowConnection();
			returnAllTopicsForForum = clConnection.prepareStatement(RETURN_ALL_TOPICS_FOR_FORUM_SQL);
			returnAllTopicsForForum.setString(1, siteId);
			returnAllTopicsForForum.setString(2, "" +forumId);
			if(topicId != null)
				returnAllTopicsForForum.setString(3, "" +topicId);
			
			
			forumsAndTopicsRS = returnAllTopicsForForum.executeQuery();			
			HashMap<Long, DecoratedForumInfo> dfHM = getDecoratedForumsAndTopics(forumsAndTopicsRS);
			
			
			for (Iterator iterator = users.iterator(); iterator.hasNext();) {
        		String userId = (String) iterator.next();        		
        		//by passing a null, we can ignore all message tool calls (speeding up the process)
        		DecoratedCompiledMessageStats dcms = getDMessageStats(userId, siteId, site, dfHM, null);
        		returnHM.put(userId, Integer.valueOf(dcms.getUnreadForumsAmt()));
			}
						
		} catch (IdUnusedException e) {
			LOG.error(e);
		} catch (SQLException e) {
			LOG.error(e);
		} finally{
			try {
				if(forumsAndTopicsRS != null)
					forumsAndTopicsRS.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			try {
				if(returnAllTopicsForForum != null)
					returnAllTopicsForForum.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			
			SqlService.returnConnection(clConnection);
		}
		
		return returnHM;
	}
	
	public void updateSynopticMessagesForForumComparingOldMessagesCount(String siteId, Long forumId, Long topicId, HashMap<String, Integer> previousCountHM){
		if(previousCountHM != null){

			// get new count Hash Map for comparison
			HashMap<String, Integer> newCountHM = getUserToNewMessagesForForumMap(siteId, forumId, topicId);

			if(newCountHM != null){
				//loop through new count HM and compare:
				Set<String> users = newCountHM.keySet();


				int oldForumCount = 0;
				int newForumCount = 0;
				int forumCountDiff = 0;

				for (Iterator iterator = users.iterator(); iterator.hasNext();) {
					String userId = (String) iterator.next();

					oldForumCount = 0;
					newForumCount = 0;
					forumCountDiff = 0;

					Integer oldForumCountInt = previousCountHM.get(userId);
					if(oldForumCountInt != null){
						oldForumCount = oldForumCountInt.intValue();
					}	

					Integer newForumCountInt = newCountHM.get(userId);
					if(newForumCountInt != null){
						newForumCount = newForumCountInt.intValue();
					}

					forumCountDiff = newForumCount - oldForumCount;

					this.updateDifferenceForumSynopticInfoHelper(userId, siteId, forumCountDiff);
				}
			}
		}
	}
	
	
	private DecoratedCompiledMessageStats getDMessageStats(String userId, String siteId, Site site, HashMap<Long, DecoratedForumInfo> dfHM, HashMap<String, Integer> unreadMessagesHM){
		
		final DecoratedCompiledMessageStats dcms = new DecoratedCompiledMessageStats();

		// Check if tool within site
		// if so, get stats for just this site

		boolean isMessageForumsPageInSite = isMessageForumsPageInSite(site);
		dcms.setSiteName(site.getTitle());
		dcms.setSiteId(siteId);
		
		//MSGCNTR-430 if this is the anon user we can't actually do anything more -DH
		if (userId == null) {
			return dcms;
		}
		
		if (isMessageForumsPageInSite || isMessagesPageInSite(site)) 
		{
			if(unreadMessagesHM != null){

				// Get private message area so we can get the private message forum so we can get the
				// List of topics so we can get the Received topic to finally determine number of unread messages
				// only check if Messages & Forums in site, just Messages is on by default
				boolean isEnabled;



				if (isMessageForumsPageInSite) {
					final Area area = pvtMessageManager.getPrivateMessageArea(siteId);
					isEnabled = area.getEnabled().booleanValue();
				}
				else {
					isEnabled = true;
				}

				if (isEnabled) {
					Integer newMessageCount = unreadMessagesHM.get(userId);
					if(newMessageCount != null){
						dcms.setUnreadPrivateAmt(newMessageCount.intValue());
					}								
				}
			}
		}

		if (isMessageForumsPageInSite || isForumsPageInSite(site)) 
		{
			Set<Long> dfKeySet = null;
			int unreadForum = 0;
			

			if(dfHM != null){
				boolean isSuperUser = SecurityService.isSuperUser(userId);
				//site has forums added to the tool
				dfKeySet = dfHM.keySet();

				boolean isInstructor = getForumManager().isInstructor(userId, "/site/" + siteId);
				
				boolean hasOverridingPermission = false;
				if(isInstructor
						|| isSuperUser){
					hasOverridingPermission = true;
				}
				boolean isAreaAvailable = true;
				if(!hasOverridingPermission){
					//need to check that the area hasn't been disabled:
					Area area = forumManager.getDiscussionForumArea(siteId);
					if(area != null){
						isAreaAvailable = area.getAvailability();
					}
				}
					
				if(isAreaAvailable){
					for (Iterator iterator = dfKeySet.iterator(); iterator.hasNext();) {
						Long dfId = (Long) iterator.next();

						DecoratedForumInfo dForum = dfHM.get(dfId);



						// Only count unread messages for forums the user can view:
						if ((dForum.getIsDraft().equals(Boolean.FALSE) && dForum.getAvailability()) ||
								hasOverridingPermission ||
								forumManager.isForumOwner(dfId, dForum.getCreator(), userId, "/site/" + siteId))
						{ 

							final Iterator<DecoratedTopicsInfo> topicIter = dForum.getTopics().iterator();

							while (topicIter.hasNext()) 
							{
								DecoratedTopicsInfo topic = (DecoratedTopicsInfo) topicIter.next();

								Long topicId = topic.getTopicId();
								Boolean isTopicDraft = topic.getIsDraft();
								Boolean isTopicModerated = topic.getIsModerated();
								Boolean isTopicLocked = topic.getIsLocked();
								String topicOwner = topic.getCreator();

								//Only count unread messages for topics the user can view:
								if ((isTopicDraft.equals(Boolean.FALSE) && topic.getAvailability())
										|| isInstructor
										|| isSuperUser
										||forumManager.isTopicOwner(topicId, topicOwner, userId, "/site/" + siteId)){ 

									if (getUiPermissionsManager().isRead(topicId, isTopicDraft, dForum.getIsDraft(), userId, siteId))
									{
										if (!isTopicModerated.booleanValue() || (isTopicModerated.booleanValue() && 
												getUiPermissionsManager().isModeratePostings(topicId, dForum.getIsLocked(), dForum.getIsDraft(), isTopicLocked, isTopicDraft, userId, siteId)))
										{
											unreadForum += getMessageManager().findUnreadMessageCountByTopicIdByUserId(topicId, userId);
										}
										else
										{	
											// b/c topic is moderated and user does not have mod perm, user may only
											// see approved msgs or pending/denied msgs authored by user
											unreadForum += getMessageManager().findUnreadViewableMessageCountByTopicIdByUserId(topicId, userId);

										}
									}
								}
							}
						}
					}
				}
			}

			dcms.setUnreadForumsAmt(unreadForum);
		}


		return dcms;
	}
	
	
	/**
	 * Returns List to populate page if on Home page of a site
	 * 
	 * @return
	 * 		List of DecoratedCompiledMessageStats for a particular site
	 */
	private DecoratedCompiledMessageStats getSiteContents(String siteId, String userId) 
	{
		String NEW_MESSAGE_COUNT_SQL = "SELECT USER_ID, count(*) unread_messages " +
										"FROM MFR_PVT_MSG_USR_T message " +									
										"where READ_STATUS = 0 and USER_ID = ? and CONTEXT_ID = ? " +
										"Group By USER_ID";
		
		String RETURN_ALL_FORUMS_AND_TOPICS_SQL = "select forum.ID as FORUM_ID, topic.ID as TOPIC_ID, forum.DRAFT as isForumDraft, topic.DRAFT as isTopicDraft, topic.MODERATED as isTopicModerated, forum.LOCKED as isForumLocked, topic.LOCKED as isTopicLocked, forum.CREATED_BY as forumCreatedBy, topic.CREATED_BY as topicCreatedBy, forum.AVAILABILITY as forumAvailability, topic.AVAILABILITY as topicAvailability  " +
													"from MFR_AREA_T area, MFR_OPEN_FORUM_T forum, MFR_TOPIC_T topic " + 
													"Where area.ID = forum.surrogateKey and forum.ID = topic.of_surrogateKey " +
													"and area.CONTEXT_ID = ?";
		
		Connection clConnection = null;  	
		PreparedStatement newMessageCount = null;
		PreparedStatement returnAllForumsAndTopics = null;
		ResultSet forumsAndTopicsRS = null;
		ResultSet newMessagesCountRS = null;
		
		
		final DecoratedCompiledMessageStats dcms = new DecoratedCompiledMessageStats();

		try{
			clConnection = SqlService.borrowConnection();
			newMessageCount = clConnection.prepareStatement(NEW_MESSAGE_COUNT_SQL);
			newMessageCount.setString(1, userId);
			newMessageCount.setString(2, siteId);
			returnAllForumsAndTopics = clConnection.prepareStatement(RETURN_ALL_FORUMS_AND_TOPICS_SQL);			
			returnAllForumsAndTopics.setString(1, siteId);
			
			Site site = getSite(siteId);
			
			forumsAndTopicsRS = returnAllForumsAndTopics.executeQuery();			
			HashMap<Long, DecoratedForumInfo> dfHM = getDecoratedForumsAndTopics(forumsAndTopicsRS);
			
			newMessagesCountRS = newMessageCount.executeQuery();
			HashMap<String, Integer> unreadMessagesHM = getUnreadMessagesHM(newMessagesCountRS);
						
			return getDMessageStats(userId, siteId, site, dfHM, unreadMessagesHM);
			
		}catch(IdUnusedException e) {
			LOG.error("IdUnusedException while trying to check if site has MF tool.");
		} catch (SQLException e) {
			LOG.error(e);
		} finally{
			
			try {
				if(forumsAndTopicsRS != null)
					forumsAndTopicsRS.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			
			try {
				if(newMessagesCountRS != null)
					newMessagesCountRS.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			
			try {
				if(returnAllForumsAndTopics != null)
					returnAllForumsAndTopics.close();
			} catch (Exception e) {
				LOG.warn(e);
			}	
			
			try {
				if(newMessageCount != null)
					newMessageCount.close();
			} catch (Exception e) {
				LOG.warn(e);
			}
			
			SqlService.returnConnection(clConnection);
		}
		
		return dcms;
	}
	
	
	private HashMap<Long, DecoratedForumInfo> getDecoratedForumsAndTopics(ResultSet rs){
		HashMap<Long, DecoratedForumInfo> returnHM = new HashMap<Long, DecoratedForumInfo>();

		try {
			String FORUM_CREATED_BY, TOPIC_CREATED_BY;
			Long FORUM_ID, TOPIC_ID;
			Boolean IS_TOPIC_DRAFT, IS_FORUM_DRAFT, IS_TOPIC_MODERATED, IS_FORUM_LOCKED, IS_TOPIC_LOCKED, FORUM_AVAILABILITY, TOPIC_AVAILABILITY;

			while(rs.next()){
				FORUM_ID = rs.getLong("FORUM_ID");
				TOPIC_ID = rs.getLong("TOPIC_ID");
				IS_TOPIC_DRAFT = rs.getBoolean("isTopicDraft");
				IS_FORUM_DRAFT = rs.getBoolean("isForumDraft");
				IS_TOPIC_MODERATED = rs.getBoolean("isTopicModerated");
				IS_FORUM_LOCKED = rs.getBoolean("isForumLocked");
				IS_TOPIC_LOCKED = rs.getBoolean("isTopicLocked");
				FORUM_CREATED_BY = rs.getString("forumCreatedBy");
				TOPIC_CREATED_BY = rs.getString("topicCreatedBy");
				FORUM_AVAILABILITY = rs.getBoolean("forumAvailability");
				TOPIC_AVAILABILITY = rs.getBoolean("topicAvailability");


				//hashmap already has this site id, now look for forum id:
				if(returnHM.containsKey(FORUM_ID)){						
					DecoratedTopicsInfo dTopic = new DecoratedTopicsInfo(TOPIC_ID, IS_TOPIC_LOCKED, IS_TOPIC_DRAFT, TOPIC_AVAILABILITY, IS_TOPIC_MODERATED, TOPIC_CREATED_BY);
					returnHM.get(FORUM_ID).addTopic(dTopic);
				}else{
					//this is a new forum, so add it to the list						
					DecoratedTopicsInfo dTopic = new DecoratedTopicsInfo(TOPIC_ID, IS_TOPIC_LOCKED, IS_TOPIC_DRAFT, TOPIC_AVAILABILITY, IS_TOPIC_MODERATED, TOPIC_CREATED_BY);
					DecoratedForumInfo dForum = new DecoratedForumInfo(FORUM_ID, IS_FORUM_LOCKED, IS_FORUM_DRAFT, FORUM_AVAILABILITY, FORUM_CREATED_BY);
					dForum.addTopic(dTopic);

					returnHM.put(FORUM_ID, dForum);
				}												
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return returnHM;
	}
	
	public HashMap<String, Integer> getUnreadMessagesHM(ResultSet rs){
		HashMap<String, Integer> returnHM = new HashMap<String, Integer>();
		
		if(rs != null){
			try{
				String userId;
				Integer messageCount;
			while(rs.next()){
				userId = rs.getString("USER_ID");
				messageCount = Integer.valueOf(rs.getInt("unread_messages"));

				returnHM.put(userId, messageCount);		
			}
			}catch(Exception e){
				LOG.error(e);
			}
		}
		
		return returnHM;
	}

	/**
	 * @return TRUE if Messages & Forums (Message Center) exists in this site,
	 *         FALSE otherwise
	 */
	private boolean isMessageForumsPageInSite(Site thisSite) {
		if (mfPageInSiteMap == null) {
			mfPageInSiteMap = new HashMap();
		}
		
		Boolean isMFPageInSite;
		if ((isMFPageInSite = (Boolean) mfPageInSiteMap.get(thisSite)) == null) {
			isMFPageInSite = isToolInSite(thisSite, DiscussionForumService.MESSAGE_CENTER_ID);
			mfPageInSiteMap.put(thisSite, isMFPageInSite);
		}
		
		return isMFPageInSite;
	}
	
	/**
	 * Return TRUE if tool with id passed in exists in site passed in
	 * FALSE otherwise.
	 * 
	 * @param thisSite
	 * 			Site object to check
	 * @param toolId
	 * 			Tool id to be checked
	 * 
	 * @return
	 */
	private boolean isToolInSite(Site thisSite, String toolId) {
		final Collection toolsInSite = thisSite.getTools(toolId);

		return ! toolsInSite.isEmpty();		
	}

	
	/**
	 * Returns the Site object for this id, if it exists.
	 * If not, returns IdUnusedException
	 * 
	 * @param siteId
	 * 			The site id to check
	 * 
	 * @return
	 * 			Site object for this id
	 */
	private Site getSite(String siteId) 
	throws IdUnusedException {
		if (sitesMap == null) {
			sitesMap = new HashMap();
		}
	
		if (sitesMap.get(siteId) == null) {
			Site site = SiteService.getSite(siteId);
			sitesMap.put(site.getId(), site);
			return site;
		}
		else {
			return (Site) sitesMap.get(siteId);
		}
	}

	
	/**
	 * @return TRUE if Messages tool exists in this site,
	 *         FALSE otherwise
	 */
	private boolean isMessagesPageInSite(Site thisSite) {
		return isToolInSite(thisSite, DiscussionForumService.MESSAGES_TOOL_ID);
	}
	
	/**
	 * @return TRUE if Forums tool exists in this site,
	 *         FALSE otherwise
	 */
	private boolean isForumsPageInSite(Site thisSite) {
		return isToolInSite(thisSite, DiscussionForumService.FORUMS_TOOL_ID);
	}
	
	
	public MessageForumsMessageManager getMessageManager() {
		return messageManager;
	}

	public void setMessageManager(MessageForumsMessageManager messageManager) {
		this.messageManager = messageManager;
	}
	
	public UIPermissionsManager getUiPermissionsManager() {
		return uiPermissionsManager;
	}

	public void setUiPermissionsManager(UIPermissionsManager uiPermissionsManager) {
		this.uiPermissionsManager = uiPermissionsManager;
	}
	
	public PrivateMessageManager getPvtMessageManager() {
		return pvtMessageManager;
	}

	public void setPvtMessageManager(PrivateMessageManager pvtMessageManager) {
		this.pvtMessageManager = pvtMessageManager;
	}

	public MessageForumsTypeManager getTypeManager() {
		return typeManager;
	}

	public void setTypeManager(MessageForumsTypeManager typeManager) {
		this.typeManager = typeManager;
	}
	
	public DiscussionForumManager getForumManager() {
		return forumManager;
	}

	public void setForumManager(DiscussionForumManager forumManager) {
		this.forumManager = forumManager;
	}
	
	/**
	 * Used to store synoptic information for a users unread messages.
	 * Whether on the Home page of a site or in MyWorkspace determines
	 * what properties are filled.
	 * <p>
	 * If in MyWorkspace, each object contains the number of unread
	 * Private Messages and number of unread Discussion Forum messages.
	 * </p>
	 * <p>
	 * If in the Home page of a site, each object contains either the
	 * number of unread Private Messages or number of unread Discussion 
	 * Forum messages.</p>
	 * 
	 * @author josephrodriguez
	 *
	 */
	public class DecoratedCompiledMessageStats {
		private String siteName;
		private String siteId;
		
		/** MyWorkspace information */
		private int unreadPrivateAmt = 0;
		private int unreadForumsAmt = 0;
		private String mcPageURL;
		private String privateMessagesUrl;
		private boolean messagesandForums;
		private boolean messages;
		private boolean forums;
		
		public String getSiteName() {
			return siteName;
		}

		public void setSiteName(String siteName) {
			this.siteName = siteName;
		}

		public int getUnreadPrivateAmt() {
			return unreadPrivateAmt;
		}

		public void setUnreadPrivateAmt(int unreadPrivateAmt) {
			this.unreadPrivateAmt = unreadPrivateAmt;
		}

		public int getUnreadForumsAmt() {
			return unreadForumsAmt;
		}

		public void setUnreadForumsAmt(int unreadForumsAmt) {
			this.unreadForumsAmt = unreadForumsAmt;
		}

		public String getMcPageURL() {
			return mcPageURL;
		}

		public void setMcPageURL(String mcPageURL) {
			this.mcPageURL = mcPageURL;
		}

		public String getSiteId() {
			return siteId;
		}

		public void setSiteId(String siteId) {
			this.siteId = siteId;
		}

		public String getPrivateMessagesUrl() {
			return privateMessagesUrl;
		}

		public void setPrivateMessagesUrl(String privateMessagesUrl) {
			this.privateMessagesUrl = privateMessagesUrl;
		}

		public boolean isMessagesandForums() {
			return messagesandForums;
		}

		public void setMessagesandForums(boolean messagesandForums) {
			this.messagesandForums = messagesandForums;
		}

		public boolean isMessages() {
			return messages;
		}

		public void setMessages(boolean messages) {
			this.messages = messages;
		}

		public boolean isForums() {
			return forums;
		}

		public void setForums(boolean forums) {
			this.forums = forums;
		}
	}
	
public class DecoratedForumInfo{
		
		private Long forumId;
		private Boolean isLocked, isDraft, availability;
		private String creator;
		private ArrayList<DecoratedTopicsInfo> topics = new ArrayList<DecoratedTopicsInfo>();
		
		public DecoratedForumInfo(Long forumId, Boolean isLocked, Boolean isDraft, Boolean availability, String creator){
			this.forumId = forumId;
			this.isLocked = isLocked;
			this.isDraft = isDraft;
			this.creator = creator;
			this.availability = availability;
		}

		public Long getForumId() {
			return forumId;
		}

		public void setForumId(Long forumId) {
			this.forumId = forumId;
		}

		public Boolean getIsLocked() {
			return isLocked;
		}

		public void setIsLocked(Boolean isLocked) {
			this.isLocked = isLocked;
		}

		public Boolean getIsDraft() {
			return isDraft;
		}

		public void setIsDraft(Boolean isDraft) {
			this.isDraft = isDraft;
		}

		public String getCreator() {
			return creator;
		}

		public void setCreator(String creator) {
			this.creator = creator;
		}

		public void addTopic(DecoratedTopicsInfo dTopics){
			topics.add(dTopics);
		}
		
		public ArrayList<DecoratedTopicsInfo> getTopics(){
			return topics;
		}

		public Boolean getAvailability() {
			return availability;
		}

		public void setAvailability(Boolean availability) {
			this.availability = availability;
		}
	}

	public class DecoratedTopicsInfo{
		
		private Long topicId;
		private Boolean isLocked, isDraft, isModerated, availability;
		private String creator;
		
		public DecoratedTopicsInfo(Long topicId, Boolean isLocked, Boolean isDraft, Boolean availability, Boolean isModerated, String creator){
			this.topicId = topicId;
			this.isLocked = isLocked;
			this.isDraft = isDraft;
			this.isModerated = isModerated;
			this.creator = creator;
			this.availability = availability;
		}

		public Long getTopicId() {
			return topicId;
		}

		public void setTopicId(Long topicId) {
			this.topicId = topicId;
		}

		public Boolean getIsLocked() {
			return isLocked;
		}

		public void setIsLocked(Boolean isLocked) {
			this.isLocked = isLocked;
		}

		public Boolean getIsDraft() {
			return isDraft;
		}

		public void setIsDraft(Boolean isDraft) {
			this.isDraft = isDraft;
		}

		public Boolean getIsModerated() {
			return isModerated;
		}

		public void setIsModerated(Boolean isModerated) {
			this.isModerated = isModerated;
		}

		public String getCreator() {
			return creator;
		}

		public void setCreator(String creator) {
			this.creator = creator;
		}

		public Boolean getAvailability() {
			return availability;
		}

		public void setAvailability(Boolean availability) {
			this.availability = availability;
		}
	}

	public void updateAllSiteTitles(final String siteId, final String siteTitle) {
		HibernateCallback hcb = new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query q = session.getNamedQuery(QUERY_UPDATE_ALL_SITE_TITLES);
				q.setParameter("siteTitle", siteTitle, Hibernate.STRING);
				q.setParameter("siteId", siteId, Hibernate.STRING);
				return q.executeUpdate();
			}
		};

		getHibernateTemplate().execute(hcb);
	}
}

{'fraction_non_alphanumeric': 0.08981930005987046, 'fraction_numerical': 0.0008844500081641539, 'mean_word_length': 3.9927309782608695, 'pattern_counts': {'":': 0, '<': 77, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6726721', 'n_tokens_mistral': 27960, 'n_tokens_neox': 22945, 'n_words': 5100}