text:
package org.sakaiproject.tool.messageforums;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Locale;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.validator.EmailValidator;
import org.sakaiproject.api.app.messageforums.Area;
import org.sakaiproject.api.app.messageforums.Attachment;
import org.sakaiproject.api.app.messageforums.DBMembershipItem;
import org.sakaiproject.api.app.messageforums.DefaultPermissionsManager;
import org.sakaiproject.api.app.messageforums.DiscussionForumService;
import org.sakaiproject.api.app.messageforums.HiddenGroup;
import org.sakaiproject.api.app.messageforums.MembershipManager;
import org.sakaiproject.api.app.messageforums.Message;
import org.sakaiproject.api.app.messageforums.MessageForumsForumManager;
import org.sakaiproject.api.app.messageforums.MessageForumsMessageManager;
import org.sakaiproject.api.app.messageforums.MessageForumsTypeManager;
import org.sakaiproject.api.app.messageforums.PrivateForum;
import org.sakaiproject.api.app.messageforums.PrivateMessage;
import org.sakaiproject.api.app.messageforums.PrivateMessageRecipient;
import org.sakaiproject.api.app.messageforums.PrivateTopic;
import org.sakaiproject.api.app.messageforums.SynopticMsgcntrManager;
import org.sakaiproject.api.app.messageforums.Topic;
import org.sakaiproject.api.app.messageforums.UserPreferencesManager;
import org.sakaiproject.api.app.messageforums.ui.PrivateMessageManager;
import org.sakaiproject.authz.api.Member;
import org.sakaiproject.authz.api.PermissionsHelper;
import org.sakaiproject.authz.cover.SecurityService;
import org.sakaiproject.component.app.messageforums.MembershipItem;
import org.sakaiproject.component.app.messageforums.dao.hibernate.HiddenGroupImpl;
import org.sakaiproject.component.app.messageforums.dao.hibernate.PrivateMessageImpl;
import org.sakaiproject.component.app.messageforums.dao.hibernate.PrivateTopicImpl;
import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.component.cover.ServerConfigurationService;
import org.sakaiproject.content.api.ContentHostingService;
import org.sakaiproject.content.api.FilePickerHelper;
import org.sakaiproject.entity.api.Reference;
import org.sakaiproject.event.api.Event;
import org.sakaiproject.event.api.LearningResourceStoreService;
import org.sakaiproject.event.api.LearningResourceStoreService.LRS_Actor;
import org.sakaiproject.event.api.LearningResourceStoreService.LRS_Object;
import org.sakaiproject.event.api.LearningResourceStoreService.LRS_Statement;
import org.sakaiproject.event.api.LearningResourceStoreService.LRS_Verb;
import org.sakaiproject.event.api.LearningResourceStoreService.LRS_Verb.SAKAI_VERB;
import org.sakaiproject.event.cover.EventTrackingService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.site.api.Group;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.cover.SiteService;
import org.sakaiproject.time.cover.TimeService;
import org.sakaiproject.tool.api.ToolSession;
import org.sakaiproject.tool.api.Session;
import org.sakaiproject.tool.cover.SessionManager;
import org.sakaiproject.tool.cover.ToolManager;
import org.sakaiproject.tool.messageforums.ui.DecoratedAttachment;
import org.sakaiproject.tool.messageforums.ui.PermissionBean;
import org.sakaiproject.tool.messageforums.ui.PrivateForumDecoratedBean;
import org.sakaiproject.tool.messageforums.ui.PrivateMessageDecoratedBean;
import org.sakaiproject.tool.messageforums.ui.PrivateTopicDecoratedBean;
import org.sakaiproject.user.api.User;
import org.sakaiproject.user.api.UserNotDefinedException;
import org.sakaiproject.user.cover.UserDirectoryService;
import org.sakaiproject.util.FormattedText;
import org.sakaiproject.util.ResourceLoader;
import org.sakaiproject.util.Validator;
import org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException;

public class PrivateMessagesTool
{

  private static final Log LOG = LogFactory.getLog(PrivateMessagesTool.class);

  private static final String MESSAGECENTER_PRIVACY_URL = "messagecenter.privacy.url";
  private static final String MESSAGECENTER_PRIVACY_TEXT = "messagecenter.privacy.text";

  private static final String MESSAGECENTER_BUNDLE = "org.sakaiproject.api.app.messagecenter.bundle.Messages";
  private static final String PERMISSIONS_BUNDLE = "org.sakaiproject.api.app.messagecenter.bundle.permissions";

  private static final ResourceLoader rb = new ResourceLoader(MESSAGECENTER_BUNDLE);

  /**
   * List individual private messages details
   */
  private static final String REPLY_SUBJECT_PREFIX = "pvt_reply_prefix";
  private static final String FORWARD_SUBJECT_PREFIX = "pvt_forward_prefix";
  //sakai-reply allF
  private static final String ReplyAll_SUBJECT_PREFIX = "pvt_replyall_prefix";
  private static final String ALERT = "pvt_alert";
  private static final String NO_MATCH_FOUND = "pvt_no_match_found";
  private static final String MISSING_BEG_END_DATE = "pvt_missing_date_range";
  private static final String CREATE_DIFF_FOLDER_NAME = "pvt_create_diff_folder_name";
  private static final String FOLDER_NAME_BLANK = "pvt_folder_name_blank";
  private static final String ENTER_FOLDER_NAME = "pvt_enter_new_folder_name";
  private static final String ENTER_SHORTER_NAME = "pvt_enter_shorter_folder_name";
  private static final String CONFIRM_FOLDER_DELETE = "pvt_delete_folder_confirm";
  private static final String CANNOT_DEL_REVISE_FOLDER = "pvt_no_delete_revise_folder";
  private static final String PROVIDE_VALID_EMAIL = "pvt_provide_email_addr";
  private static final String CONFIRM_PERM_MSG_DELETE = "pvt_confirm_perm_msg_delete";
  private static final String SELECT_MSGS_TO_DELETE = "pvt_select_msgs_to_delete";
  private static final String SELECT_RECIPIENT_LIST_FOR_REPLY = "pvt_select_reply_recipients_list";
  private static final String MISSING_SUBJECT = "pvt_missing_subject";
  private static final String MISSING_SUBJECT_DRAFT = "pvt_missing_subject_draft";
  private static final String SELECT_MSG_RECIPIENT = "pvt_select_msg_recipient";
  private static final String MULTIPLE_WINDOWS = "pvt_multiple_windows";

  private static final String CONFIRM_MSG_DELETE = "pvt_confirm_msg_delete";
  private static final String ENTER_SEARCH_TEXT = "pvt_enter_search_text";
  private static final String MOVE_MSG_ERROR = "pvt_move_msg_error";
  private static final String NO_MARKED_READ_MESSAGE = "pvt_no_message_mark_read";
  private static final String NO_MARKED_DELETE_MESSAGE = "pvt_no_message_mark_delete";
  private static final String NO_MARKED_MOVE_MESSAGE = "pvt_no_message_mark_move";
  private static final String MULTIDELETE_SUCCESS_MSG = "pvt_deleted_success";
  private static final String PERM_DELETE_SUCCESS_MSG = "pvt_perm_deleted_success";

  public static final String RECIPIENTS_UNDISCLOSED = "pvt_bccUndisclosed";

  /** Used to determine if this is combined tool or not */
  private static final String MESSAGECENTER_TOOL_ID = "sakai.messagecenter";
  private static final String MESSAGECENTER_HELPER_TOOL_ID = "sakai.messageforums.helper";
  private static final String MESSAGES_TOOL_ID = "sakai.messages";
  private static final String FORUMS_TOOL_ID = "sakai.forums";

  /**
   *Dependency Injected
   */
  private PrivateMessageManager prtMsgManager;
  private MessageForumsMessageManager messageManager;
  private MessageForumsForumManager forumManager;
  private ErrorMessages errorMessages;
  private MembershipManager membershipManager;
  private SynopticMsgcntrManager synopticMsgcntrManager;
  private UserPreferencesManager userPreferencesManager;

  /** Dependency Injected   */
  private MessageForumsTypeManager typeManager;
  private ContentHostingService contentHostingService;

  /** Navigation for JSP   */
  public static final String MAIN_PG="main";
  public static final String DISPLAY_MESSAGES_PG="pvtMsg";
  public static final String SELECTED_MESSAGE_PG="pvtMsgDetail";
  public static final String COMPOSE_MSG_PG="compose";
  public static final String COMPOSE_FROM_PG="msgForum:mainOrHp";
  public static final String MESSAGE_SETTING_PG="pvtMsgSettings";
  public static final String MESSAGE_FOLDER_SETTING_PG="pvtMsgFolderSettings";
  public static final String SEARCH_RESULT_MESSAGES_PG="pvtMsgEx";
  public static final String DELETE_MESSAGES_PG="pvtMsgDelete";
  public static final String DELETE_FOLDER_PG="pvtMsgFolderDelete";
  public static final String MESSAGE_STATISTICS_PG="pvtMsgStatistics";
  public static final String MESSAGE_HOME_PG="pvtMsgHpView";
  public static final String MESSAGE_REPLY_PG="pvtMsgReply";

  public static final String MESSAGE_FORWARD_PG="pvtMsgForward";

  //sakai-huxt pvtMsgReplyAll
  public static final String MESSAGE_ReplyAll_PG="pvtMsgReplyAll";

  public static final String DELETE_MESSAGE_PG="pvtMsgDelete";
  public static final String REVISE_FOLDER_PG="pvtMsgFolderRevise";
  public static final String MOVE_MESSAGE_PG="pvtMsgMove";
  public static final String ADD_FOLDER_IN_FOLDER_PG="pvtMsgFolderInFolderAdd";
  public static final String ADD_MESSAGE_FOLDER_PG="pvtMsgFolderAdd";
  public static final String PVTMSG_COMPOSE = "pvtMsgCompose";

  //need to modified to support internationalization by huxt
  /** portlet configuration parameter values**/
  public static final String PVTMSG_MODE_RECEIVED = "pvt_received";
  public static final String PVTMSG_MODE_SENT = "pvt_sent";
  public static final String PVTMSG_MODE_DELETE = "pvt_deleted";
  public static final String PVTMSG_MODE_DRAFT = "pvt_drafts";
  public static final String PVTMSG_MODE_CASE = "Personal Folders";

  public static final String RECIPIANTS_ENTIRE_CLASS= "All Participants";
  public static final String RECIPIANTS_ALL_INSTRUCTORS= "All Instructors";

  public static final String SET_AS_YES="yes";
  public static final String SET_AS_NO="no";

  public static final String THREADED_VIEW = "threaded";

  //huxt
  public static final String EXTERNAL_TOPIC_ID = "pvtMsgTopicId";
  public static final String EXTERNAL_WHICH_TOPIC = "selectedTopic";

  PrivateForumDecoratedBean decoratedForum;

  private List aggregateList = new ArrayList();

  private Area area;
  private PrivateForum forum;
  private List<PrivateTopic> pvtTopics=new ArrayList<PrivateTopic>();
  private List decoratedPvtMsgs;
  //huxt
  private String msgNavMode="privateMessages" ;//============
  private PrivateMessageDecoratedBean detailMsg ;
  private boolean viewChanged = false;

  private String currentMsgUuid; //this is the message which is being currently edited/displayed/deleted
  private List selectedItems;

  private String userName;    //current user
  private Date time ;       //current time

  //delete confirmation screen - single delete
  private boolean deleteConfirm=false ; //used for displaying delete confirmation message in same jsp
  private boolean validEmail=true ;

  //Compose Screen-webpage
  private List selectedComposeToList = new ArrayList();
  private List selectedComposeBccList = new ArrayList();
  private String composeSendAsPvtMsg=SET_AS_YES; // currently set as Default as change by user is allowed
  private boolean booleanEmailOut= Boolean.parseBoolean(ServerConfigurationService.getString("mc.messages.ccEmailDefault", "false"));
  private String composeSubject ;
  private String composeBody;
  private String selectedLabel="pvt_priority_normal" ;   //defautl set
  private List totalComposeToList = null;
  private List totalComposeToBccList = null;
  private List totalComposeToListRecipients;

  //Delete items - Checkbox display and selection - Multiple delete
  private List selectedDeleteItems;
  private boolean multiDeleteSuccess;
  private String multiDeleteSuccessMsg;
  private List totalDisplayItems=new ArrayList();

  // Move to folder - Checkbox display and selection - Multiple move to folder
  private List selectedMoveToFolderItems;

  //reply to
  private String replyToBody;
  private String replyToSubject;

  //forwarding
  private String forwardBody;
  private String forwardSubject;

//reply to all-huxt

  private String replyToAllBody;
  private String replyToAllSubject;

  //Setting Screen
  private String activatePvtMsg=SET_AS_NO;
  private String forwardPvtMsg=SET_AS_NO;
  private String forwardPvtMsgEmail;
  private boolean superUser;
  private String sendToEmail;

  //message header screen
  private String searchText="";
  private String selectView;

  //return to previous page after send msg
  private String fromMainOrHp = null;

  // for compose, are we coming from main page?
  private boolean fromMain;

  // Message which will be marked as replied
  private PrivateMessage replyingMessage;

  //////////////////////

  //=====================need to be modified to support internationalization - by huxt
  /** The configuration mode, received, sent,delete, case etc ... */
  public static final String STATE_PVTMSG_MODE = "pvtmsg.mode";

  private Map courseMemberMap;

  public static final String SORT_SUBJECT_ASC = "subject_asc";
  public static final String SORT_SUBJECT_DESC = "subject_desc";
  public static final String SORT_AUTHOR_ASC = "author_asc";
  public static final String SORT_AUTHOR_DESC = "author_desc";
  public static final String SORT_DATE_ASC = "date_asc";
  public static final String SORT_DATE_DESC = "date_desc";
  public static final String SORT_LABEL_ASC = "label_asc";
  public static final String SORT_LABEL_DESC = "label_desc";
  public static final String SORT_TO_ASC = "to_asc";
  public static final String SORT_TO_DESC = "to_desc";
  public static final String SORT_ATTACHMENT_ASC = "attachment_asc";
  public static final String SORT_ATTACHMENT_DESC = "attachment_desc";

  private boolean selectedComposedlistequalCurrentuser=false;

  /** sort member */
  private String sortType = SORT_DATE_DESC;

  private int setDetailMsgCount = 0;

  private static final String PERMISSIONS_PREFIX = "msg.";

  private boolean instructor = false;

  private List<SelectItem> nonHiddenGroups = new ArrayList<SelectItem>();
  private List<HiddenGroup> hiddenGroups = new ArrayList();
  private static final String DEFAULT_NON_HIDDEN_GROUP_ID = "-1";
  private String DEFAULT_NON_HIDDEN_GROUP_TITLE = "hiddenGroups_selectGroup";
  private String selectedNonHiddenGroup = DEFAULT_NON_HIDDEN_GROUP_ID;
  private static final String PARAM_GROUP_ID = "groupId";
  private boolean currentSiteHasGroups = false;
  private Boolean displayHiddenGroupsMsg = null;

  private boolean showProfileInfoMsg = false;
  private boolean showProfileLink = false;

  public PrivateMessagesTool()
  {
	  showProfileInfoMsg = ServerConfigurationService.getBoolean("msgcntr.messages.showProfileInfo", true);
	  showProfileLink = showProfileInfoMsg && ServerConfigurationService.getBoolean("profile2.profile.link.enabled", true);
  }

  /**
   * @return
   */
  public MessageForumsTypeManager getTypeManager()
  {
    return typeManager;
  }

  /**
   * @param prtMsgManager
   */
  public void setPrtMsgManager(PrivateMessageManager prtMsgManager)
  {
    this.prtMsgManager = prtMsgManager;
  }

  /**
   * @param messageManager
   */
  public void setMessageManager(MessageForumsMessageManager messageManager)
  {
    this.messageManager = messageManager;
  }

  /**
   * @param membershipManager
   */
  public void setMembershipManager(MembershipManager membershipManager)
  {
    this.membershipManager = membershipManager;
  }

  /**
   * @param typeManager
   */
  public void setTypeManager(MessageForumsTypeManager typeManager)
  {
    this.typeManager = typeManager;
  }

  public void initializePrivateMessageArea()
  {
    /** get area per request */
	area = prtMsgManager.getPrivateMessageArea();

    if (! area.getEnabled() && isMessages()) {
    	area.setEnabled(true);
    }

    // reset these in case the allowed recipients (such as hidden groups) was updated
    totalComposeToList = null;
    totalComposeToBccList = null;
    displayHiddenGroupsMsg = null;

    if (getUserId() != null && (getPvtAreaEnabled() || isInstructor() || isEmailPermit())){
      PrivateForum pf = prtMsgManager.initializePrivateMessageArea(area, aggregateList);
      pf = prtMsgManager.initializationHelper(pf, area);
      pvtTopics = pf.getTopics();
      Collections.sort(pvtTopics, PrivateTopicImpl.TITLE_COMPARATOR);   //changed to date comparator
      forum=pf;
      activatePvtMsg = (Boolean.TRUE.equals(area.getEnabled())) ? SET_AS_YES : SET_AS_NO;
      sendToEmail = area.getSendToEmail() + "";
      forwardPvtMsg = (Boolean.TRUE.equals(pf.getAutoForward())) ? SET_AS_YES : SET_AS_NO;
      forwardPvtMsgEmail = pf.getAutoForwardEmail();
      hiddenGroups = new ArrayList<HiddenGroup>();
      if(area != null && area.getHiddenGroups() != null){
	for(Iterator itor = area.getHiddenGroups().iterator(); itor.hasNext();){
    	  HiddenGroup group = (HiddenGroup) itor.next();
    	  hiddenGroups.add(group);
	}
      }
    }
  }

  /**
   * Property created rather than setErrorMessage for design requirement
   * @return
   */
  public boolean isDispError()
  {
    if (isInstructor() && !getPvtAreaEnabled())
    {
      return true;
    }
    else
    {
      return false;
    }
  }

  public boolean getPvtAreaEnabled()
  {
    if(area == null) {
    	initializePrivateMessageArea();
    }
	  return area.getEnabled().booleanValue();
  }

  /**
   *
   * @return true if a copy of the message is always sent to the recipient email address(es)
   * per the site-wide setting
   */
  public boolean isEmailCopyAlways() {
      if (area == null) {
          initializePrivateMessageArea();
      }

      return !isEmailCopyDisabled() && area.getSendToEmail() == Area.EMAIL_COPY_ALWAYS;
  }

  public boolean isEmailCopyDisabled(){
	  return ServerConfigurationService.getBoolean("mc.messages.ccEmailDisabled", false);
  }

  /**
   *
   * @return true if the sender may choose whether a copy of the message is sent to recipient
   * email address(es)
   */
  public boolean isEmailCopyOptional() {
      if (area == null) {
          initializePrivateMessageArea();
      }

      return !isEmailCopyDisabled() && area.getSendToEmail() == Area.EMAIL_COPY_OPTIONAL;
  }

  public boolean isEmailForwardDisabled(){
	  return ServerConfigurationService.getBoolean("mc.messages.forwardEmailDisabled", false);
  }

  public boolean isShowSettingsLink(){
	  if(isInstructor()){
		  //if the site has groups, then show the settings link b/c there
		  //are settings for groups
		  if(getCurrentSiteHasGroups()){
			  return true;
		  }else{
			  //if no groups and all email settings are disabled, there's no
			  //settings to show, so don't show the link
			  return !isEmailForwardDisabled() || !isEmailCopyDisabled();
		  }
	  }else{
		  //students only see forward options, if it's hidden, don't show this link
		  return !isEmailForwardDisabled();
	  }
  }

  //Return decorated Forum
  public PrivateForumDecoratedBean getDecoratedForum()
  {
      PrivateForumDecoratedBean decoratedForum = new PrivateForumDecoratedBean(getForum()) ;

      /** only load topics/counts if area is enabled */

      int totalUnreadMessages = 0;

      if (getPvtAreaEnabled() && decoratedForum.getForum() != null){

    	int countForFolderNum = 0;// only three folder
    	Iterator<PrivateTopic> iterator = pvtTopics.iterator();
    	//MSGCNTR-472 we need the first three but need to guard against there being < 3 elements
        for (int i = 0;i < 3 && iterator.hasNext(); i++)//only three times
        {
          PrivateTopic topic = (PrivateTopic) iterator.next();

          if (topic != null)
          {

          	/** filter topics by context and type*/
            if (topic.getTypeUuid() != null
            		&& topic.getTypeUuid().equals(typeManager.getUserDefinedPrivateTopicType())
            	  && topic.getContextId() != null && !topic.getContextId().equals(prtMsgManager.getContextId())){
               continue;
            }

            PrivateTopicDecoratedBean decoTopic= new PrivateTopicDecoratedBean(topic) ;

            // folder uuid
            String typeUuid = getPrivateMessageTypeFromContext(topic.getTitle());

            countForFolderNum++;

            decoTopic.setTotalNoMessages(prtMsgManager.findMessageCount(typeUuid, aggregateList));

            decoTopic.setUnreadNoMessages(prtMsgManager.findUnreadMessageCount(typeUuid, aggregateList));
            totalUnreadMessages += decoTopic.getUnreadNoMessages();

            decoratedForum.addTopic(decoTopic);
          }
        }

        while(iterator.hasNext())//add more folders
        {
               PrivateTopic topic = (PrivateTopic) iterator.next();
               if (topic != null)
               {

               /** filter topics by context and type*/
                 if (topic.getTypeUuid() != null
                 && topic.getTypeUuid().equals(typeManager.getUserDefinedPrivateTopicType())
                   && topic.getContextId() != null && !topic.getContextId().equals(prtMsgManager.getContextId())){
                    continue;
                 }

                 PrivateTopicDecoratedBean decoTopic= new PrivateTopicDecoratedBean(topic) ;

                 String typeUuid = getPrivateMessageTypeFromContext(topic.getTitle());

                 decoTopic.setTotalNoMessages(prtMsgManager.findMessageCount(typeUuid, aggregateList));
                 decoTopic.setUnreadNoMessages(prtMsgManager.findUnreadMessageCount(typeUuid,aggregateList));
                 totalUnreadMessages += decoTopic.getUnreadNoMessages();
                 decoratedForum.addTopic(decoTopic);
               }

        }

      }//if  getPvtAreaEnabled()

      //update syntopic info:
      if(getUserId() != null){
    	  setMessagesSynopticInfoHelper(getUserId(), getSiteId(), totalUnreadMessages, SynopticMsgcntrManager.NUM_OF_ATTEMPTS);
      }

    return decoratedForum ;
  }

  public void setMessagesSynopticInfoHelper(String userId, String siteId, int unreadMessagesCount, int numOfAttempts) {
	  try {
		  getSynopticMsgcntrManager().setMessagesSynopticInfoHelper(userId, siteId, unreadMessagesCount);
	  } catch (HibernateOptimisticLockingFailureException holfe) {

		  // failed, so wait and try again
		  try {
			  Thread.sleep(SynopticMsgcntrManager.OPT_LOCK_WAIT);
		  } catch (InterruptedException e) {
			  e.printStackTrace();
		  }

		  numOfAttempts--;

		  if (numOfAttempts <= 0) {
			  System.out
			  .println("PrivateMessagesTool: setMessagesSynopticInfoHelper: HibernateOptimisticLockingFailureException no more retries left");
			  holfe.printStackTrace();
		  } else {
			  System.out
			  .println("PrivateMessagesTool: setMessagesSynopticInfoHelper: HibernateOptimisticLockingFailureException: attempts left: "
					  + numOfAttempts);
			  setMessagesSynopticInfoHelper(userId, siteId,
					  unreadMessagesCount, numOfAttempts);
		  }
	  }

  }

  public List getDecoratedPvtMsgs()
  {
  	/**
  	    avoid apply_request_values and render_response from calling this method on postback
  	    solution -- only call during render_response phase
  	    8/29/07 JLR - if coming from the synoptic tool, we need to process
  	*/

  	if (!FacesContext.getCurrentInstance().getRenderResponse() && !viewChanged &&
  			getExternalParameterByKey(EXTERNAL_WHICH_TOPIC) == null) {
  		return decoratedPvtMsgs;
  	}

	if(selectView!=null && selectView.equalsIgnoreCase(THREADED_VIEW))
    {
    	this.rearrageTopicMsgsThreaded(false);
    	return decoratedPvtMsgs;
    }

  	// coming from synoptic view, need to change the msgNavMode
	if (msgNavMode == null)
	{//=======Recibidios by huxt
		msgNavMode = (getExternalParameterByKey(EXTERNAL_WHICH_TOPIC) == null) ? //"selectedTopic"
						forumManager.getTopicByUuid(getExternalParameterByKey(EXTERNAL_TOPIC_ID)).getTitle() ://"pvtMsgTopicid"
						getExternalParameterByKey(EXTERNAL_WHICH_TOPIC);
	}

  	decoratedPvtMsgs=new ArrayList();
  	String typeUuid;

   	typeUuid = getPrivateMessageTypeFromContext(msgNavMode);//=======Recibidios by huxt

  	/** support for sorting */
  	/* if the view was changed to "All Messages", we want to retain the previous
  	 * sort setting. Otherwise, the user has selected a different sort setting.
  	 * Also retain sort setting if user has hit "Check All"
  	 */
  	if ((!viewChanged || sortType == null) && !selectAll)
  	{
  		String sortColumnParameter = getExternalParameterByKey("sortColumn");

  		if ("subject".equals(sortColumnParameter)){
  			sortType = (SORT_SUBJECT_ASC.equals(sortType)) ? SORT_SUBJECT_DESC : SORT_SUBJECT_ASC;
  		}
  		else if ("author".equals(sortColumnParameter)){
  			sortType = (SORT_AUTHOR_ASC.equals(sortType)) ? SORT_AUTHOR_DESC : SORT_AUTHOR_ASC;
  		}
  		else if ("date".equals(sortColumnParameter)){
  			sortType = (SORT_DATE_ASC.equals(sortType)) ? SORT_DATE_DESC : SORT_DATE_ASC;
  		}
  		else if ("label".equals(sortColumnParameter)){
  			sortType = (SORT_LABEL_ASC.equals(sortType)) ? SORT_LABEL_DESC : SORT_LABEL_ASC;
  		}
  		else if ("to".equals(sortColumnParameter)){
  			sortType = (SORT_TO_ASC.equals(sortType)) ? SORT_TO_DESC : SORT_TO_ASC;
  		}
  		else if ("attachment".equals(sortColumnParameter)){
  			sortType = (SORT_ATTACHMENT_ASC.equals(sortType)) ? SORT_ATTACHMENT_DESC : SORT_ATTACHMENT_ASC;
  		}
  		else{
  			sortType = SORT_DATE_DESC;
  		}
  	}

  	viewChanged = false;

    /** add support for sorting */
    if (SORT_SUBJECT_ASC.equals(sortType)){
    	decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_SUBJECT,
          PrivateMessageManager.SORT_ASC);
    }
    else if (SORT_SUBJECT_DESC.equals(sortType)){
    	decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_SUBJECT,
          PrivateMessageManager.SORT_DESC);
    }
    else if (SORT_AUTHOR_ASC.equals(sortType)){
    	decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_AUTHOR,
          PrivateMessageManager.SORT_ASC);
    }
    else if (SORT_AUTHOR_DESC.equals(sortType)){
    	decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_AUTHOR,
          PrivateMessageManager.SORT_DESC);
    }
    else if (SORT_DATE_ASC.equals(sortType)){
    	decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_DATE,
          PrivateMessageManager.SORT_ASC);
    }
    else if (SORT_DATE_DESC.equals(sortType)){
    	decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_DATE,
          PrivateMessageManager.SORT_DESC);
    }
    else if (SORT_LABEL_ASC.equals(sortType)){
    	decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_LABEL,
          PrivateMessageManager.SORT_ASC);
    }
    else if (SORT_LABEL_DESC.equals(sortType)){
    	decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_LABEL,
          PrivateMessageManager.SORT_DESC);
    }
    else if (SORT_TO_ASC.equals(sortType)){
        // the recipient list is stored as a CLOB in Oracle, so we cannot use the
    	// db query to obtain the sorted list - cannot order by CLOB
    	/*decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_TO,
          PrivateMessageManager.SORT_ASC);*/
    	decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_DATE,
    	          PrivateMessageManager.SORT_ASC);
    	Collections.sort(decoratedPvtMsgs, PrivateMessageImpl.RECIPIENT_LIST_COMPARATOR_ASC);
    }
    else if (SORT_TO_DESC.equals(sortType)){
    	// the recipient list is stored as a CLOB in Oracle, so we cannot use the
    	// db query to obtain the sorted list - cannot order by CLOB
    	/*decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_TO,
          PrivateMessageManager.SORT_DESC);*/
    	decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_DATE,
    	          PrivateMessageManager.SORT_ASC);
    	Collections.sort(decoratedPvtMsgs, PrivateMessageImpl.RECIPIENT_LIST_COMPARATOR_DESC);
    }
    else if (SORT_ATTACHMENT_ASC.equals(sortType)){
    	decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_ATTACHMENT,
          PrivateMessageManager.SORT_ASC);
    }
    else if (SORT_ATTACHMENT_DESC.equals(sortType)){
    	decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_ATTACHMENT,
          PrivateMessageManager.SORT_DESC);
    }

    decoratedPvtMsgs = createDecoratedDisplay(decoratedPvtMsgs);

    //pre/next message
    if(decoratedPvtMsgs != null )
    {
   		setMessageBeanPreNextStatus();
    }

    return decoratedPvtMsgs ;
  }

  private void setMessageBeanPreNextStatus()
  {
	  List tempMsgs = decoratedPvtMsgs;
      for(int i=0; i<tempMsgs.size(); i++)
      {
        PrivateMessageDecoratedBean dmb = (PrivateMessageDecoratedBean)tempMsgs.get(i);
        if(i==0)
        {
          dmb.setHasPre(false);
          if(i==(tempMsgs.size()-1))
          {
              dmb.setHasNext(false);
          }
          else
          {
              dmb.setHasNext(true);
          }
        }
        else if(i==(tempMsgs.size()-1))
        {
          dmb.setHasPre(true);
          dmb.setHasNext(false);
        }
        else
        {
          dmb.setHasNext(true);
          dmb.setHasPre(true);
        }
      }
  }

  public void setDecoratedPvtMsgs(List displayPvtMsgs)
  {
    this.decoratedPvtMsgs=displayPvtMsgs;
  }

  public String getMsgNavMode()
  {
    return msgNavMode ;
  }

  public PrivateMessageDecoratedBean getDetailMsg()
  {
    return detailMsg ;
  }

  public void setDetailMsg(PrivateMessageDecoratedBean detailMsg)
  {
    this.detailMsg = detailMsg;
  }

  public String getCurrentMsgUuid()
  {
    return currentMsgUuid;
  }

  public void setCurrentMsgUuid(String currentMsgUuid)
  {
    this.currentMsgUuid = currentMsgUuid;
  }

  public List getSelectedItems()
  {
    return selectedItems;
  }

  public void setSelectedItems(List selectedItems)
  {
    this.selectedItems=selectedItems ;
  }

  public boolean isDeleteConfirm()
  {
    return deleteConfirm;
  }

  public void setDeleteConfirm(boolean deleteConfirm)
  {
    this.deleteConfirm = deleteConfirm;
  }

  public boolean isValidEmail()
  {
    return validEmail;
  }
  public void setValidEmail(boolean validEmail)
  {
    this.validEmail = validEmail;
  }

  //Deleted page - checkbox display and selection
  public List getSelectedDeleteItems()
  {
    return selectedDeleteItems;
  }
  public List getTotalDisplayItems()
  {
    return totalDisplayItems;
  }
  public void setTotalDisplayItems(List totalDisplayItems)
  {
    this.totalDisplayItems = totalDisplayItems;
  }
  public void setSelectedDeleteItems(List selectedDeleteItems)
  {
    this.selectedDeleteItems = selectedDeleteItems;
  }

  //Compose Getter and Setter
  public String getComposeBody()
  {
    return composeBody;
  }

  public void setComposeBody(String composeBody)
  {
    this.composeBody = composeBody;
  }

  public String getSelectedLabel()
  {
    return selectedLabel;
  }

  public void setSelectedLabel(String selectedLabel)
  {
    this.selectedLabel = selectedLabel;
  }

  public boolean getBooleanEmailOut() {
	  return booleanEmailOut;
  }

  public void setBooleanEmailOut(boolean booleanEmailOut) {
	  this.booleanEmailOut= booleanEmailOut;
  }

  public PrivateMessage getReplyingMessage() {
	  return replyingMessage;
  }

  public void setReplyingMessage(PrivateMessage replyingMessage) {
	  this.replyingMessage = replyingMessage;
  }

  /**
   *
   * @return true if the Messages tool setting in combination with the author-defined
   * {@link #getBooleanEmailOut()} setting requires a copy of the message to be sent to
   * recipient(s) email
   */
  public boolean isSendEmail() {
      boolean sendEmail;
      if (isEmailCopyAlways() ||
              (isEmailCopyOptional() && getBooleanEmailOut())) {
          sendEmail = true;
      } else {
          sendEmail = false;
      }

      return sendEmail;
  }

  public String getComposeSendAsPvtMsg()
  {
    return composeSendAsPvtMsg;
  }

  public void setComposeSendAsPvtMsg(String composeSendAsPvtMsg)
  {
    this.composeSendAsPvtMsg = composeSendAsPvtMsg;
  }

  public String getComposeSubject()
  {
    return composeSubject;
  }

  public void setComposeSubject(String composeSubject)
  {
    this.composeSubject = composeSubject;
  }

  public void setSelectedComposeToList(List selectedComposeToList)
  {
    this.selectedComposeToList = selectedComposeToList;
  }

  public void setSelectedComposeBccList(List selectedComposeBccList)
  {
	  this.selectedComposeBccList = selectedComposeBccList;
  }

  public void setTotalComposeToList(List totalComposeToList)
  {
    this.totalComposeToList = totalComposeToList;
  }

  public List getSelectedComposeToList()
  {
    return selectedComposeToList;
  }

  public List getSelectedComposeBccList()
  {
	  return selectedComposeBccList;
  }

  private String getSiteTitle(){
	  try {
		return SiteService.getSite(ToolManager.getCurrentPlacement().getContext()).getTitle();
	} catch (IdUnusedException e) {
		e.printStackTrace();
	}
	return "";
  }

  private String getSiteId() {
	  return ToolManager.getCurrentPlacement().getContext();
  }

  private String getContextSiteId()
  {
	 return "/site/" + ToolManager.getCurrentPlacement().getContext();
  }

  public List getTotalComposeToList()
  {
      if (totalComposeToList == null) {
          initializeComposeToLists();
      }

      List<SelectItem> selectItemList = new ArrayList<SelectItem>();
      for (Iterator i = totalComposeToList.iterator(); i.hasNext();) {
          MembershipItem item = (MembershipItem) i.next();
          selectItemList.add(new SelectItem(item.getId(), item.getName()));
      }

      return selectItemList;
  }

  public List getTotalComposeToBccList() {
      if (totalComposeToBccList == null) {
          initializeComposeToLists();
      }

      List<SelectItem> selectItemList = new ArrayList<SelectItem>();
      for (Iterator i = totalComposeToBccList.iterator(); i.hasNext();) {
          MembershipItem item = (MembershipItem) i.next();
          selectItemList.add(new SelectItem(item.getId(), item.getName()));
      }

      return selectItemList;
  }

  /**
   * Since the courseMemberMap generates new uuids each time it is called, and
   * these uuids are used to identify the recipients of the message when the user
   * sends the message, we need to do the logic for the "To" and "Bcc" lists together,
   * utilizing the same courseMemberMap. This will set the values for the
   * totalComposeToList and totalComposeToBccList.
   */
  private void initializeComposeToLists() {
      totalComposeToList = new ArrayList();
      totalComposeToBccList = new ArrayList();

      List<String> hiddenGroupIds = getHiddenGroupIds(area.getHiddenGroups());
      courseMemberMap = membershipManager.getFilteredCourseMembers(true, getHiddenGroupIds(area.getHiddenGroups()));
      List members = membershipManager.convertMemberMapToList(courseMemberMap);

      List<SelectItem> selectItemList = new ArrayList<SelectItem>();
      // we need to filter out the hidden groups since they will only appear as recipients in the bcc list
      for (Iterator i = members.iterator(); i.hasNext();) {
          MembershipItem item = (MembershipItem) i.next();
          if (hiddenGroupIds != null && item.getGroup() != null && hiddenGroupIds.contains(item.getGroup().getTitle())) {
              // hidden groups only appear in the bcc list
              totalComposeToBccList.add(item);
          } else {
              totalComposeToList.add(item);
              totalComposeToBccList.add(item);
          }
      }
  }

  public boolean isDisplayHiddenGroupsMsg() {
      if (displayHiddenGroupsMsg == null) {
          displayHiddenGroupsMsg = hiddenGroups != null && !hiddenGroups.isEmpty() && prtMsgManager.isAllowToViewHiddenGroups();
      }

      return displayHiddenGroupsMsg;
  }

  private List<String> getHiddenGroupIds(Set hiddenGroups){
	  List<String> returnList = new ArrayList<String>();

	  if(hiddenGroups != null){
		  for(Iterator itor = hiddenGroups.iterator(); itor.hasNext();){
	    	  HiddenGroup group = (HiddenGroup) itor.next();
	    	  returnList.add(group.getGroupId());
		  }
	  }

	  return returnList;
  }

  /**
   *
   * @param id
   * @return
   */
  public String getUserSortNameById(String id){
    try
    {
      User user=UserDirectoryService.getUser(id) ;
      if (ServerConfigurationService.getBoolean("msg.displayEid", true))
      {
    	  userName= user.getSortName() + " (" + user.getDisplayId() + ")";
      }
      else
      {
    	  userName= user.getSortName();
      }
    }
    catch (UserNotDefinedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
    return userName;
  }

  public String getUserName() {
   String userId=SessionManager.getCurrentSessionUserId();
   try
   {
     User user=UserDirectoryService.getUser(userId) ;
     if (ServerConfigurationService.getBoolean("msg.displayEid", true))
     {
    	 userName= user.getDisplayName() + " (" + user.getDisplayId() + ")";
     }
     else {
    	 userName= user.getDisplayName();
     }
   }
   catch (UserNotDefinedException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}
   return userName;
  }

  public String getUserId()
  {
    return SessionManager.getCurrentSessionUserId();
  }

  public TimeZone getUserTimeZone() {
	  return userPreferencesManager.getTimeZone();
  }

  //Reply time
  public Date getTime()
  {
    return new Date();
  }
  //Reply to page
  public String getReplyToBody() {
    return replyToBody;
  }
  public void setReplyToBody(String replyToBody) {
    this.replyToBody=replyToBody;
  }
  public String getReplyToSubject()
  {
    return replyToSubject;
  }
  public void setReplyToSubject(String replyToSubject)
  {
    this.replyToSubject = replyToSubject;
  }

  // Forward a message
  public String getForwardBody() {
    return forwardBody;
  }
  public void setForwardBody(String forwardBody) {
    this.forwardBody=forwardBody;
  }
  public String getForwardSubject()
  {
    return forwardSubject;
  }
  public void setForwardSubject(String forwardSubject)
  {
    this.forwardSubject = forwardSubject;
  }

  //message header Getter
  public String getSearchText()
  {
    return searchText ;
  }
  public void setSearchText(String searchText)
  {
    this.searchText=searchText;
  }
  public String getSelectView()
  {
    return selectView ;
  }
  public void setSelectView(String selectView)
  {
    this.selectView=selectView ;
  }

  public boolean isMultiDeleteSuccess()
  {
	return multiDeleteSuccess;
  }

  public void setMultiDeleteSuccess(boolean multiDeleteSuccess)
  {
	this.multiDeleteSuccess = multiDeleteSuccess;
  }

  public String getMultiDeleteSuccessMsg()
  {
	return multiDeleteSuccessMsg;
  }

  public void setMultiDeleteSuccessMsg(String multiDeleteSuccessMsg)
  {
	this.multiDeleteSuccessMsg = multiDeleteSuccessMsg;
  }

public boolean isFromMain() {
	return fromMain;
}

public String getServerUrl() {
    return ServerConfigurationService.getServerUrl();
 }

public boolean getShowProfileInfoMsg() {
    return showProfileInfoMsg;
}

public boolean getShowProfileLink() {
	return showProfileLink;
}

public void processChangeSelectView(ValueChangeEvent eve)
  {
    multiDeleteSuccess = false;
    String currentValue = (String) eve.getNewValue();
  	if (!currentValue.equalsIgnoreCase(THREADED_VIEW) && selectView != null && selectView.equals(THREADED_VIEW))
  	{
  		selectView = "";
  		viewChanged = true;
  		getDecoratedPvtMsgs();
  		return;
    }
  	else if (currentValue.equalsIgnoreCase(THREADED_VIEW))
  	{
  		selectView = THREADED_VIEW;
  		if (searchPvtMsgs != null && !searchPvtMsgs.isEmpty())
  			this.rearrageTopicMsgsThreaded(true);
  		else
  			this.rearrageTopicMsgsThreaded(false);
  		return;
  	}
  }

  public void rearrageTopicMsgsThreaded(boolean searcModeOn)
  {
	  List msgsList = new ArrayList();

	  if(searcModeOn)
	  {
		  for(int i=0; i<searchPvtMsgs.size(); i++)
		  {
			  msgsList.add((PrivateMessageDecoratedBean)searchPvtMsgs.get(i));
		  }
		  searchPvtMsgs.clear();
	  }else
	  {
		  // always start with the decorated pm in ascending date order
		  String typeUuid = getPrivateMessageTypeFromContext(msgNavMode);
		  decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_DATE,
		          PrivateMessageManager.SORT_ASC);
		  decoratedPvtMsgs = createDecoratedDisplay(decoratedPvtMsgs);

		  for(int i=0; i<decoratedPvtMsgs.size(); i++)
		  {
			  msgsList.add((PrivateMessageDecoratedBean)decoratedPvtMsgs.get(i));
		  }
		  decoratedPvtMsgs.clear();
	  }

	  if(msgsList != null)
	  {
		  List tempMsgsList = new ArrayList();
		  for(int i=0; i<msgsList.size(); i++)
		  {
			  tempMsgsList.add((PrivateMessageDecoratedBean)msgsList.get(i));
		  }
		  Iterator iter = tempMsgsList.iterator();
		  while(iter.hasNext())
		  {
			  List allRelatedMsgs = messageManager.getAllRelatedMsgs(
					  ((PrivateMessageDecoratedBean)iter.next()).getMsg().getId());
			  List currentRelatedMsgs = new ArrayList();
			  if(allRelatedMsgs != null && allRelatedMsgs.size()>0)
			  {
				  Long msgId = ((Message)allRelatedMsgs.get(0)).getId();
				  PrivateMessage pvtMsg= (PrivateMessage) prtMsgManager.getMessageById(msgId);
				  PrivateMessageDecoratedBean pdb = new PrivateMessageDecoratedBean(pvtMsg);
				  pdb.setDepth(-1);
				  boolean firstEleAdded = false;
				  for(int i=0; i<msgsList.size(); i++)
				  {
					  PrivateMessageDecoratedBean tempPMDB = (PrivateMessageDecoratedBean)msgsList.get(i);
					  if (tempPMDB.getMsg().getId().equals(pdb.getMsg().getId()))
					  {
						  tempPMDB.setDepth(0);
						  currentRelatedMsgs.add(tempPMDB);
						  firstEleAdded = true;
						  recursiveGetThreadedMsgsFromList(msgsList, allRelatedMsgs, currentRelatedMsgs, tempPMDB);
						  break;
					  }
				  }
				  if(!firstEleAdded)
					  recursiveGetThreadedMsgsFromList(msgsList, allRelatedMsgs, currentRelatedMsgs, pdb);
			  }
			  for(int i=0; i<currentRelatedMsgs.size(); i++)
			  {
				  if(searcModeOn)
				  {
					  searchPvtMsgs.add((PrivateMessageDecoratedBean)currentRelatedMsgs.get(i));
				  }else
				  {
					  decoratedPvtMsgs.add((PrivateMessageDecoratedBean)currentRelatedMsgs.get(i));
				  }

				  tempMsgsList.remove((PrivateMessageDecoratedBean)currentRelatedMsgs.get(i));
			  }

			  iter = tempMsgsList.iterator();
		  }
	  }

	  setMessageBeanPreNextStatus();

  }

  private void recursiveGetThreadedMsgsFromList(List msgsList,
  		List allRelatedMsgs, List returnList,
      PrivateMessageDecoratedBean currentMsg)
  {
    for (int i = 0; i < allRelatedMsgs.size(); i++)
    {
      Long msgId = ((Message)allRelatedMsgs.get(i)).getId();
	  PrivateMessage pvtMsg= (PrivateMessage) prtMsgManager.getMessageById(msgId);
	  PrivateMessageDecoratedBean thisMsgBean = new PrivateMessageDecoratedBean(pvtMsg);

      Message thisMsg = thisMsgBean.getMsg();
      boolean existedInCurrentUserList = false;
      for(int j=0; j< msgsList.size(); j++)
      {
      	PrivateMessageDecoratedBean currentUserBean =
      		(PrivateMessageDecoratedBean)msgsList.get(j);
        if (thisMsg.getInReplyTo() != null
            && thisMsg.getInReplyTo().getId().equals(
                currentMsg.getMsg().getId())
						&& currentUserBean.getMsg().getId().equals(thisMsg.getId()))
        {
          currentUserBean.setDepth(currentMsg.getDepth() + 1);
          if(currentMsg.getDepth() > -1)
          {
          	currentUserBean.setUiInReply(((PrivateMessageDecoratedBean)returnList.get(returnList.size()-1)).getMsg());
          }
          returnList.add(currentUserBean);
          existedInCurrentUserList = true;
          recursiveGetThreadedMsgsFromList(msgsList, allRelatedMsgs, returnList, currentUserBean);
          break;
        }
      }
      if(!existedInCurrentUserList)
      {
        if(thisMsg.getInReplyTo() != null
            && thisMsg.getInReplyTo().getId().equals(
                currentMsg.getMsg().getId()))
        {
          thisMsgBean.setDepth(currentMsg.getDepth());
          recursiveGetThreadedMsgsFromList(msgsList, allRelatedMsgs, returnList, thisMsgBean);
        }
      }
    }
  }

  //////////////////////////////////////////////////////////////////////////////////
  /**
   * called when any topic like Received/Sent/Deleted clicked
   * @return - pvtMsg
   */
  private String selectedTopicTitle="";
  private String selectedTopicId="";
  public String getSelectedTopicTitle()
  {
    return selectedTopicTitle ;
  }
  public void setSelectedTopicTitle(String selectedTopicTitle)
  {
    this.selectedTopicTitle=selectedTopicTitle;
  }
  public String getSelectedTopicId()
  {
    return selectedTopicId;
  }
  public void setSelectedTopicId(String selectedTopicId)
  {
    this.selectedTopicId=selectedTopicId;
  }

  public String processActionHome()
  {
    LOG.debug("processActionHome()");
    msgNavMode = "privateMessages";
    multiDeleteSuccess = false;
    if (searchPvtMsgs != null)
    	searchPvtMsgs.clear();
    return  MAIN_PG;
  }
  public String processActionPrivateMessages()
  {
    LOG.debug("processActionPrivateMessages()");
    msgNavMode = "privateMessages";
    multiDeleteSuccess = false;
    if (searchPvtMsgs != null)
    	searchPvtMsgs.clear();
    return  MESSAGE_HOME_PG;
  }
  public String processDisplayForum()
  {
    LOG.debug("processDisplayForum()");
    if (searchPvtMsgs != null)
    	searchPvtMsgs.clear();
    return DISPLAY_MESSAGES_PG;
  }

  public String processDisplayMessages()
  {
    LOG.debug("processDisplayMessages()");
    if (searchPvtMsgs != null)
    	searchPvtMsgs.clear();
    return SELECTED_MESSAGE_PG;
  }

  public void initializeFromSynoptic()
  {

	  if(getUserId() != null){

	    /** reset sort type */
	    sortType = SORT_DATE_DESC;

	    setSelectedTopicId(getExternalParameterByKey(EXTERNAL_TOPIC_ID));
	   	selectedTopic = new PrivateTopicDecoratedBean(forumManager.getTopicByUuid(getExternalParameterByKey(EXTERNAL_TOPIC_ID)));
	    selectedTopicTitle = getExternalParameterByKey(EXTERNAL_WHICH_TOPIC);

	    //set prev/next topic details
	    PrivateForum pf = forumManager.getPrivateForumByOwnerAreaNullWithAllTopics(getUserId());

	    if (pf == null)
	    {
	    	initializePrivateMessageArea();
	    }
	    else
	    {
	    	pvtTopics = pf.getTopics();
	    	forum = pf;
	    }

	    msgNavMode=getSelectedTopicTitle();

	    //set prev/next topic details
	    setPrevNextTopicDetails(msgNavMode);
	  }
  }

  public String processPvtMsgTopic()
  {
    LOG.debug("processPvtMsgTopic()");

    /** reset sort type */
    sortType = SORT_DATE_DESC;

    setSelectedTopicId(getExternalParameterByKey(EXTERNAL_TOPIC_ID));
   	selectedTopic = new PrivateTopicDecoratedBean(forumManager.getTopicByUuid(getExternalParameterByKey(EXTERNAL_TOPIC_ID)));
   	selectedTopicTitle = forumManager.getTopicByUuid(getExternalParameterByKey(EXTERNAL_TOPIC_ID)).getTitle();
   	//"selectedTopicTitle"= "Recibidos"
    msgNavMode=getSelectedTopicTitle();

    //set prev/next topic details
    setPrevNextTopicDetails(msgNavMode);// "Recibidos"

    return DISPLAY_MESSAGES_PG;
  }

  /**
   * process Cancel from all JSP's
   * @return - pvtMsg
   */
  public String processPvtMsgCancel() {
    LOG.debug("processPvtMsgCancel()");

    // Return to Messages & Forums page or Messages page
    if (isMessagesandForums()) {
    	return MAIN_PG;
    }
    else {
    	return MESSAGE_HOME_PG;
    }
  }

  public String processPvtMsgCancelToListView()
  {
  	return DISPLAY_MESSAGES_PG;
  }

  private String processPvtMsgDraft(){
	  //set up draft details:
	  PrivateMessage draft = prtMsgManager.initMessageWithAttachmentsAndRecipients(getDetailMsg().getMsg());
	  setDetailMsg(new PrivateMessageDecoratedBean(draft));
	  setComposeSubject(draft.getTitle());

	  setComposeBody(draft.getBody());

	  ArrayList attachments = new ArrayList();
	  for (Attachment attachment : (List<Attachment>) draft.getAttachments()) {
		  attachments.add(new DecoratedAttachment(attachment));
	  }
	  setAttachments(attachments);

	  setSelectedLabel(draft.getLabel());

	  //go to compose page
	  setFromMainOrHp();
	  fromMain = ("".equals(msgNavMode)) || ("privateMessages".equals(msgNavMode));
	  LOG.debug("processPvtMsgDraft()");
	  return PVTMSG_COMPOSE;
  }

  /**
   * called when subject of List of messages to Topic clicked for detail
   * @return - pvtMsgDetail
   */
  public String processPvtMsgDetail() {
    LOG.debug("processPvtMsgDetail()");
    multiDeleteSuccess = false;

    String msgId=getExternalParameterByKey("current_msg_detail");
    setCurrentMsgUuid(msgId) ;
    //retrive the detail for this message with currentMessageId
    for (Iterator iter = decoratedPvtMsgs.iterator(); iter.hasNext();)
    {
      PrivateMessageDecoratedBean dMsg= (PrivateMessageDecoratedBean) iter.next();
      if (dMsg.getMsg().getId().equals(Long.valueOf(msgId)))
      {

        this.setDetailMsg(dMsg);
        if(dMsg.getMsg().getDraft()){
        	return processPvtMsgDraft();
        }
        setDetailMsgCount++;

        prtMsgManager.markMessageAsReadForUser(dMsg.getMsg());

        PrivateMessage initPrivateMessage = prtMsgManager.initMessageWithAttachmentsAndRecipients(dMsg.getMsg());
        this.setDetailMsg(new PrivateMessageDecoratedBean(initPrivateMessage));
        setDetailMsgCount++;

        List recLs= initPrivateMessage.getRecipients();
        for (Iterator iterator = recLs.iterator(); iterator.hasNext();)
        {
          PrivateMessageRecipient element = (PrivateMessageRecipient) iterator.next();
          if (element != null)
          {
            if((element.getRead().booleanValue()) || (element.getUserId().equals(getUserId())) )
            {
             getDetailMsg().setHasRead(true) ;
            }
          }
        }
        if(dMsg.getMsg().getCreatedBy().equals(getUserId())){
        	//need to display all users who received the message if the user create the message
        	this.getDetailMsg().getMsg().setRecipientsAsTextBcc(dMsg.getMsg().getRecipientsAsTextBcc());
        }else{
        	//otherwise, hide the BCC information
        	this.getDetailMsg().getMsg().setRecipientsAsTextBcc("");
        }

        this.getDetailMsg().getMsg().setRecipientsAsText(dMsg.getMsg().getRecipientsAsText());
      }
    }
    this.deleteConfirm=false; //reset this as used for multiple action in same JSP

    //prev/next message
    if(decoratedPvtMsgs != null)
    {
      for(int i=0; i<decoratedPvtMsgs.size(); i++)
      {
        PrivateMessageDecoratedBean thisDmb = (PrivateMessageDecoratedBean)decoratedPvtMsgs.get(i);
        if(((PrivateMessageDecoratedBean)decoratedPvtMsgs.get(i)).getMsg().getId().toString().equals(msgId))
        {
          detailMsg.setDepth(thisDmb.getDepth());
          detailMsg.setHasNext(thisDmb.getHasNext());
          detailMsg.setHasPre(thisDmb.getHasPre());
          break;
        }
      }
    }
    //default setting for moveTo
    moveToTopic=selectedTopicId;
    LearningResourceStoreService lrss = (LearningResourceStoreService) ComponentManager
            .get("org.sakaiproject.event.api.LearningResourceStoreService");
    Event event = EventTrackingService.newEvent("msgcntr", "read private message", true);
    if (null != lrss) {
    	try{
    		lrss.registerStatement(getStatementForUserReadPvtMsg(lrss.getEventActor(event), getDetailMsg().getMsg().getTitle()), "msgcntr");
    	}catch(Exception e){
    		LOG.error(e.getMessage(), e);
    	}
    }
    return SELECTED_MESSAGE_PG;
  }

  /**
   * navigate to "reply" a private message
   * @return - pvtMsgReply
   */
  public String processPvtMsgReply() {
    LOG.debug("processPvtMsgReply()");

    setDetailMsgCount = 0;

    if (getDetailMsg() == null)
    	return null;

    PrivateMessage pm = getDetailMsg().getMsg();

    // To mark as replied when user send the reply
    this.setReplyingMessage(pm);

    String title = pm.getTitle();
	if(title != null && !title.startsWith(getResourceBundleString(REPLY_SUBJECT_PREFIX)))
		replyToSubject = getResourceBundleString(REPLY_SUBJECT_PREFIX) + ' ' + title;
	else
		replyToSubject = title;

	// format the created date according to the setting in the bundle
    SimpleDateFormat formatter_date = new SimpleDateFormat(getResourceBundleString("date_format_date"), new ResourceLoader().getLocale());
	formatter_date.setTimeZone(TimeService.getLocalTimeZone());
	String formattedCreateDate = formatter_date.format(pm.getCreated());

	SimpleDateFormat formatter_date_time = new SimpleDateFormat(getResourceBundleString("date_format_time"), new ResourceLoader().getLocale());
	formatter_date_time.setTimeZone(TimeService.getLocalTimeZone());
	String formattedCreateTime = formatter_date_time.format(pm.getCreated());

	StringBuilder replyText = new StringBuilder();

    // populate replyToBody with the reply text
	replyText.append("<br /><br />");
	replyText.append("<span style=\"font-weight:bold;font-style:italic;\">");
	replyText.append(getResourceBundleString("pvt_msg_on"));
	replyText.append(" " + formattedCreateDate + " ");
	replyText.append(getResourceBundleString("pvt_msg_at"));
	replyText.append(" " +formattedCreateTime);
	replyText.append(getResourceBundleString("pvt_msg_comma"));
    replyText.append(" " + pm.getAuthor() + " ");
    replyText.append(getResourceBundleString("pvt_msg_wrote"));
	replyText.append("</span>");

    String origBody = pm.getBody();
    if (origBody != null && origBody.trim().length() > 0) {
    	replyText.append("<br />" + pm.getBody() + "<br />");
    }

    List attachList = getDetailMsg().getAttachList();
    if (attachList != null && attachList.size() > 0) {
    	for (Iterator attachIter = attachList.iterator(); attachIter.hasNext();) {
    		DecoratedAttachment decoAttach = (DecoratedAttachment) attachIter.next();
    		if (decoAttach != null) {
    			replyText.append("<span style=\"font-style:italic;\">");
    			replyText.append(getResourceBundleString("pvt_msg_["));
    			replyText.append(decoAttach.getAttachment().getAttachmentName() );
    			replyText.append(getResourceBundleString("pvt_msg_]") + "  ");
    			replyText.append("</span>");
    		}
    	}
    }

    this.setReplyToBody(replyText.toString());
    //from message detail screen
    this.setDetailMsg(getDetailMsg()) ;

    setDetailMsgCount++;

    return MESSAGE_REPLY_PG;
  }

  /**
   * navigate to "forward" a private message
   * @return - pvtMsgForward
   */
  public String processPvtMsgForward() {
	    LOG.debug("processPvtMsgForward()");

	    setDetailMsgCount = 0;

	    if (getDetailMsg() == null)
	    	return null;

	    PrivateMessage pm = getDetailMsg().getMsg();

	    String title = pm.getTitle();
    	if(title != null && !title.startsWith(getResourceBundleString(FORWARD_SUBJECT_PREFIX)))
    		forwardSubject = getResourceBundleString(FORWARD_SUBJECT_PREFIX) + ' ' + title;
    	else
    		forwardSubject = title;

    	// format the created date according to the setting in the bundle
	    SimpleDateFormat formatter = new SimpleDateFormat(getResourceBundleString("date_format"), new ResourceLoader().getLocale());
		formatter.setTimeZone(TimeService.getLocalTimeZone());
		String formattedCreateDate = formatter.format(pm.getCreated());

		StringBuilder forwardedText = new StringBuilder();

	    // populate replyToBody with the forwarded text
		forwardedText.append(getResourceBundleString("pvt_msg_fwd_heading") + "<br /><br />" +
	    	getResourceBundleString("pvt_msg_fwd_authby", new Object[] {pm.getAuthor(), formattedCreateDate}) +  "<br />" +
	    	getResourceBundleString("pvt_msg_fwd_to", new Object[] {pm.getRecipientsAsText()}) + "<br />" +
	    	getResourceBundleString("pvt_msg_fwd_subject", new Object[] {pm.getTitle()}) + "<br />" +
	    	getResourceBundleString("pvt_msg_fwd_label", new Object[] {getDetailMsg().getLabel()}) + "<br />");

	    List attachList = getDetailMsg().getAttachList();
	    if (attachList != null && attachList.size() > 0) {
	    	forwardedText.append(getResourceBundleString("pvt_msg_fwd_attachments") + "<br />");
	    	forwardedText.append("<ul style=\"list-style-type:none;margin:0;padding:0;padding-left:0.5em;\">");
	    	for (Iterator attachIter = attachList.iterator(); attachIter.hasNext();) {
	    		DecoratedAttachment decoAttach = (DecoratedAttachment) attachIter.next();
	    		if (decoAttach != null) {
	    			forwardedText.append("<li>");
	    			// It seems like there must be a better way to do the attachment image...
	    			String fileType = decoAttach.getAttachment().getAttachmentType();
	    			String imageUrl = null;
	    			if (fileType.equalsIgnoreCase("application/vnd.ms-excel"))
	    				imageUrl = "/messageforums-tool/images/excel.gif";
	    			else if (fileType.equalsIgnoreCase("text/html"))
	    				imageUrl = "/messageforums-tool/images/html.gif";
	    			else if (fileType.equalsIgnoreCase("application/pdf"))
	    				imageUrl = "/messageforums-tool/images/pdf.gif";
	    			else if (fileType.equalsIgnoreCase("application/vnd.ms-powerpoint"))
	    				imageUrl = "/messageforums-tool/images/ppt.gif";
	    			else if (fileType.equalsIgnoreCase("text/plain"))
	    				imageUrl = "/messageforums-tool/images/text.gif";
	    			else if (fileType.equalsIgnoreCase("application/msword"))
	    				imageUrl = "/messageforums-tool/images/word.gif";

	    			if (imageUrl != null) {
	    				forwardedText.append("<img alt=\"\" src=\"" + imageUrl + "\" />");
	    			}

	    			forwardedText.append("<a href=\"" + messageManager.getAttachmentUrl(decoAttach.getAttachment().getAttachmentId()) + "\" target=\"_blank\">" + decoAttach.getAttachment().getAttachmentName() + "</a></li>");
	    		}
	    	}
	    	forwardedText.append("</ul>");
	    }
	    String origBody = pm.getBody();
	    if (origBody != null && origBody.trim().length() > 0) {
	    	forwardedText.append(pm.getBody());
	    }

	    this.setForwardBody(forwardedText.toString());
	    //from message detail screen
	    this.setDetailMsg(getDetailMsg()) ;

	    setDetailMsgCount++;

	    return MESSAGE_FORWARD_PG;
	  }

//how many letters k in string a  a= "fdh,jlg,jds,lgjd"  k=","
private   int   getNum(char letter,   String   a)
{
	int   j=0;
	for(int   i=0;   i<a.length();   i++){
		if(a.charAt(i)==(letter)){  //s.charAt(j) == 'x'
		j++;
		}
	}
	return   j;
}
/////////////modified by hu2@iupui.edu  begin
  //function: add Reply All Tools

  /**
   * navigate to "Reply to all" a private message
   * @return - pvtMsgForward
   */
  public String processPvtMsgReplyAll() {
	    LOG.debug("processPvtMsgReplyAll()");

	    setDetailMsgCount = 0;

	    if (getDetailMsg() == null)
	    	return null;

	    PrivateMessage pm = getDetailMsg().getMsg();

	    // To mark as replied when user send the reply
	    this.setReplyingMessage(pm);

	    String title = pm.getTitle();
    	if(title != null && !title.startsWith(getResourceBundleString(ReplyAll_SUBJECT_PREFIX)))
    		forwardSubject = getResourceBundleString(ReplyAll_SUBJECT_PREFIX) + ' ' + title;
    	else
    		forwardSubject = title;//forwardSubject

    	// format the created date according to the setting in the bundle
	    SimpleDateFormat formatter = new SimpleDateFormat(getResourceBundleString("date_format"), new ResourceLoader().getLocale());
		formatter.setTimeZone(TimeService.getLocalTimeZone());
		String formattedCreateDate = formatter.format(pm.getCreated());

		SimpleDateFormat formatter_date_time = new SimpleDateFormat(getResourceBundleString("date_format_time"), new ResourceLoader().getLocale());
		formatter_date_time.setTimeZone(TimeService.getLocalTimeZone());
		String formattedCreateTime = formatter_date_time.format(pm.getCreated());

		StringBuilder replyallText = new StringBuilder();

	    // populate replyToBody with the reply text
		replyallText.append("<br /><br />");
		replyallText.append("<span style=\"font-weight:bold;font-style:italic;\">");
		replyallText.append(getResourceBundleString("pvt_msg_on"));
		replyallText.append(" " + formattedCreateDate + " ");
		replyallText.append(getResourceBundleString("pvt_msg_at"));
		replyallText.append(" " +formattedCreateTime);
		replyallText.append(getResourceBundleString("pvt_msg_comma"));
		replyallText.append(" " + pm.getAuthor() + " ");
		replyallText.append(getResourceBundleString("pvt_msg_wrote"));
		replyallText.append("</span>");

	    String origBody = pm.getBody();
	    if (origBody != null && origBody.trim().length() > 0) {
	    	replyallText.append("<br />" + pm.getBody() + "<br />");
	    }

	    List attachList = getDetailMsg().getAttachList();
	    if (attachList != null && attachList.size() > 0) {
	    	for (Iterator attachIter = attachList.iterator(); attachIter.hasNext();) {
	    		DecoratedAttachment decoAttach = (DecoratedAttachment) attachIter.next();
	    		if (decoAttach != null) {
	    			replyallText.append("<span style=\"font-style:italic;\">");
	    			replyallText.append(getResourceBundleString("pvt_msg_["));
	    			replyallText.append(decoAttach.getAttachment().getAttachmentName() );
	    			replyallText.append(getResourceBundleString("pvt_msg_]") + "  ");
	    			replyallText.append("</span>");
	    		}
	    	}
	    }

	    this.setForwardBody(replyallText.toString());

	    String msgautherString=getDetailMsg().getAuthor();
	    String msgCClistString=getDetailMsg().getRecipientsAsText();

	    //remove the auther in Cc string
	    if(msgCClistString.length()>=msgautherString.length())
	    {
	    String msgCClistStringwithoutAuthor = msgCClistString;

	    String currentUserasAuther = getUserName();
	    char letter=';';
	    int  n=getNum(letter,msgCClistStringwithoutAuthor);

	    int numberofAuther=0;

	    if(n==0)
	    {numberofAuther=1;}
	    else if(n>=1)
	    { numberofAuther=n+1;}//add the end ";"
	    String[] ccSS = new String[numberofAuther];
	    ccSS=msgCClistStringwithoutAuthor.split(";");

	    StringBuffer tmpCC = new StringBuffer("");

			if((numberofAuther>0)&&(numberofAuther<=msgCClistStringwithoutAuthor.length()))
					      {

						    for(int indexCC =0;indexCC<numberofAuther;indexCC++)	    //last for ";"
						    {

						    	if(!currentUserasAuther.replaceAll(" ", ", ").equals(msgautherString)){

							    	if(!ccSS[indexCC].trim().equals(currentUserasAuther.replaceAll(" ", ", "))&&(!ccSS[indexCC].trim().equals(msgautherString)))//not equal current auther and not equal old auther
							    	{
							    		tmpCC.append(ccSS[indexCC].trim()).append("; ");

							    	}
						    	}

						    	else if(currentUserasAuther.replaceAll(" ", ", ").equals(msgautherString)){

						    		if(!ccSS[indexCC].trim().equals(currentUserasAuther.replaceAll(" ", ", "))||(!ccSS[indexCC].trim().equals(msgautherString)))//not equal current auther and not equal old auther
							    	{
							    		tmpCC.append(ccSS[indexCC].trim()).append("; ");

							    	}

						    	}

						    }

						    if(tmpCC.length()>1)
						    {
							    	tmpCC.delete(tmpCC.length()-2, tmpCC.length());//remove the ";"
							}

						    getDetailMsg().setSendToStringDecorated(tmpCC.toString());
						    getDetailMsg().getMsg().setRecipientsAsText(tmpCC.toString());

						  }

	    }

	    //remove the bcc undiclosed place holder:
	    String ccList = getDetailMsg().getMsg().getRecipientsAsText();
	    if(ccList.contains(getResourceBundleString(RECIPIENTS_UNDISCLOSED) + "; ")){
	    	ccList = ccList.replaceAll(getResourceBundleString(RECIPIENTS_UNDISCLOSED) + "; ", "");
	    }else if(ccList.contains(getResourceBundleString(RECIPIENTS_UNDISCLOSED))){
	    	ccList = ccList.replaceAll(getResourceBundleString(RECIPIENTS_UNDISCLOSED), "");
	    }
	    if(ccList.endsWith(" ")){
	    	ccList = ccList.substring(0, ccList.length() -1);
	    }
	    if(ccList.endsWith(";")){
	    	ccList = ccList.substring(0, ccList.length() -1);
	    }
	    getDetailMsg().getMsg().setRecipientsAsText(ccList);

	    this.setDetailMsg(getDetailMsg()) ;

	    setDetailMsgCount++;

	    return MESSAGE_ReplyAll_PG;//MESSAGE_FORWARD_PG;
	  }

  //////////modified by hu2@iupui.edu end
  /**
   * called from Single delete Page
   * @return - pvtMsgDetail
   */
  public String processPvtMsgDeleteConfirm() {
    LOG.debug("processPvtMsgDeleteConfirm()");

    this.setDeleteConfirm(true);
    setErrorMessage(getResourceBundleString(CONFIRM_MSG_DELETE));
    /*
     * same action is used for delete..however if user presses some other action after first
     * delete then 'deleteConfirm' boolean is reset
     */
    return SELECTED_MESSAGE_PG ;
  }

  /**
   * called from Single delete Page -
   * called when 'delete' button pressed second time
   * @return - pvtMsg
   */
  public String processPvtMsgDeleteConfirmYes() {
    LOG.debug("processPvtMsgDeleteConfirmYes()");
    if(getDetailMsg() != null)
    {
      prtMsgManager.deletePrivateMessage(getDetailMsg().getMsg(), getPrivateMessageTypeFromContext(msgNavMode));
    }
    return DISPLAY_MESSAGES_PG ;
  }

  //RESET form variable - required as the bean is in session and some attributes are used as helper for navigation
  public void resetFormVariable() {

    this.msgNavMode="" ;
    this.deleteConfirm=false;
    selectAll=false;
    attachments.clear();
    oldAttachments.clear();
  }

  /**
   * process Compose action from different JSP'S
   * @return - pvtMsgCompose
   */
  public String processPvtMsgCompose() {
	  //reset incase draft still has left over data
	  setDetailMsg(null);
	  attachments.clear();
	  oldAttachments.clear();
    setFromMainOrHp();
    fromMain = ("".equals(msgNavMode)) || ("privateMessages".equals(msgNavMode));
    LOG.debug("processPvtMsgCompose()");
    return PVTMSG_COMPOSE;
  }

  public String processPvtMsgComposeCancel()
  {
    LOG.debug("processPvtMsgComposeCancel()");
    resetComposeContents();
    if(("privateMessages").equals(getMsgNavMode()))
    {
    	return processPvtMsgReturnToMainOrHp();
    }
    else
    {
      return DISPLAY_MESSAGES_PG;
    }
  }

  public void resetComposeContents()
  {
    this.setComposeBody("");
    this.setComposeSubject("");
    this.setComposeSendAsPvtMsg(SET_AS_YES); //set as default
    this.setBooleanEmailOut(Boolean.parseBoolean(ServerConfigurationService.getString("mc.messages.ccEmailDefault", "false"))); //set as default
    this.getSelectedComposeToList().clear();
    this.getSelectedComposeBccList().clear();
    this.setReplyToSubject("");
    this.setReplyToBody("");
    this.getAttachments().clear();
    this.getAllAttachments().clear();
    //reset label
    this.setSelectedLabel("pvt_priority_normal");
  }

  public String processPvtMsgPreview(){

	  if(!hasValue(getComposeSubject()))
	  {
		  setErrorMessage(getResourceBundleString(MISSING_SUBJECT));
		  return null;
	  }

	  if(getSelectedComposeToList().size()<1 && getSelectedComposeBccList().size() < 1)
	  {
		  setErrorMessage(getResourceBundleString(SELECT_MSG_RECIPIENT));
		  return null ;
	  }
	  PrivateMessage msg;
	  if(getDetailMsg() != null && getDetailMsg().getMsg() != null && getDetailMsg().getMsg().getDraft()){
		  msg = constructMessage(false, getDetailMsg().getMsg());
		  msg.setDraft(Boolean.TRUE);
	  }else{
		  msg = constructMessage(false, null);
	  }
	  PrivateMessageDecoratedBean pmDb = new PrivateMessageDecoratedBean(msg);
	  pmDb.setIsPreview(true);
	  this.setDetailMsg(pmDb);

	  return SELECTED_MESSAGE_PG;
  }

  public String processPvtMsgPreviewSend(){
	  return processPvtMsgSend();
  }

  public String processPvtMsgPreviewBack(){
	  return PVTMSG_COMPOSE;
  }

  /**
   * process from Compose screen
   * @return - pvtMsg
   */

  //Modified to support internatioalization -by huxt
  public String processPvtMsgSend() {

    LOG.debug("processPvtMsgSend()");

    if(!hasValue(getComposeSubject()))
    {
      setErrorMessage(getResourceBundleString(MISSING_SUBJECT));
      return null;
    }

    if(getSelectedComposeToList().size()<1)
    {
      setErrorMessage(getResourceBundleString(SELECT_MSG_RECIPIENT));
      return null ;
    }

    PrivateMessage pMsg = null;
    if(getDetailMsg() != null && getDetailMsg().getMsg() != null && getDetailMsg().getMsg().getDraft()){
    	pMsg = constructMessage(true, getDetailMsg().getMsg());
    }else{
    	pMsg= constructMessage(true, null) ;
    }

    pMsg.setExternalEmail(booleanEmailOut);
    Map<User, Boolean> recipients = getRecipients();

    prtMsgManager.sendPrivateMessage(pMsg, recipients, isSendEmail());
    // if you are sending a reply
    Message replying = pMsg.getInReplyTo();
    if (replying!=null) {
    	replying = prtMsgManager.getMessageById(replying.getId());
    	if (replying!=null) {
    		prtMsgManager.markMessageAsRepliedForUser((PrivateMessage)replying);
    	}
    }

    //update synopticLite tool information:

    incrementSynopticToolInfo(recipients.keySet(), false);

    //reset contents
    resetComposeContents();

    LearningResourceStoreService lrss = (LearningResourceStoreService) ComponentManager
            .get("org.sakaiproject.event.api.LearningResourceStoreService");
    Event event = EventTrackingService.newEvent(DiscussionForumService.EVENT_MESSAGES_ADD, getEventMessage(pMsg), false);
    EventTrackingService.post(event);
    if (null != lrss) {
    	try{
    		lrss.registerStatement(getStatementForUserSentPvtMsg(lrss.getEventActor(event), pMsg.getTitle(), SAKAI_VERB.shared), "msgcntr");
    	}catch(Exception e){
    		LOG.error(e.getMessage(), e);
    	}
    }

    if(fromMainOrHp != null && !"".equals(fromMainOrHp))
    {
    	String tmpBackPage = fromMainOrHp;
    	fromMainOrHp = "";
    	return tmpBackPage;
    }
    else if(selectedTopic != null)
    {
    	msgNavMode=getSelectedTopicTitle();
    	setPrevNextTopicDetails(msgNavMode);

    	return DISPLAY_MESSAGES_PG;
    }

    // Return to Messages & Forums page or Messages page
    if (isMessagesandForums()) {
    	return MAIN_PG;
    }
    else {
    	return MESSAGE_HOME_PG;
    }
  }

  public void incrementSynopticToolInfo(Set<User> recipients, boolean updateCurrentUser){

	  String siteId = getSiteId();
	  String currentUser = getUserId();
	  List<String> userIds = new ArrayList<String>();
	  for (User user : recipients) {
		  if(updateCurrentUser || (!updateCurrentUser && !currentUser.equals(user.getId())))
			  userIds.add(user.getId());
	  }
	  incrementMessagesSynopticToolInfo(userIds, siteId, SynopticMsgcntrManager.NUM_OF_ATTEMPTS);
  }

  public void incrementMessagesSynopticToolInfo(List<String> userIds, String siteId, int numOfAttempts) {
		try {
			getSynopticMsgcntrManager().incrementMessagesSynopticToolInfo(userIds, siteId);
		} catch (HibernateOptimisticLockingFailureException holfe) {

			// failed, so wait and try again
			try {
				Thread.sleep(SynopticMsgcntrManager.OPT_LOCK_WAIT);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			numOfAttempts--;

			if (numOfAttempts <= 0) {
				System.out
						.println("PrivateMessagesTool: incrementMessagesSynopticToolInfo: HibernateOptimisticLockingFailureException no more retries left");
				holfe.printStackTrace();
			} else {
				System.out
						.println("PrivateMessagesTool: incrementMessagesSynopticToolInfo: HibernateOptimisticLockingFailureException: attempts left: "
								+ numOfAttempts);
				incrementMessagesSynopticToolInfo(userIds, siteId, numOfAttempts);
			}
		}

	}

  /**
   * process from Compose screen
   * @return - pvtMsg
   */
  public String processPvtMsgSaveDraft() {
    LOG.debug("processPvtMsgSaveDraft()");
    if(!hasValue(getComposeSubject()))
    {
      setErrorMessage(getResourceBundleString(MISSING_SUBJECT_DRAFT));
      return null ;
    }
//    if(!hasValue(getComposeBody()) )
//    {
//      setErrorMessage("Please enter message body for this compose message.");
//      return null ;
//    }
//    if(getSelectedComposeToList().size()<1)
//    {
//      setErrorMessage(getResourceBundleString(SELECT_MSG_RECIPIENT));
//      return null ;
//    }
    PrivateMessage dMsg = null;
    if(getDetailMsg() != null && getDetailMsg().getMsg() != null && getDetailMsg().getMsg().getDraft()){
    	dMsg =constructMessage(true, getDetailMsg().getMsg()) ;
    }else{
    	dMsg =constructMessage(true, null) ;
    }
    dMsg.setDraft(Boolean.TRUE);
    dMsg.setDeleted(Boolean.FALSE);
    dMsg.setExternalEmail(booleanEmailOut);

    prtMsgManager.sendPrivateMessage(dMsg, getRecipients(), isSendEmail());

    //reset contents
    resetComposeContents();

    return returnDraftPage();
  }

  private String returnDraftPage(){
	  return processPvtMsgComposeCancel();
  }
  // created separate method as to be used with processPvtMsgSend() and processPvtMsgSaveDraft()
  public PrivateMessage constructMessage(boolean clearAttachments, PrivateMessage aMsg)
  {
	  if(aMsg == null){
		  aMsg = messageManager.createPrivateMessage();
	  }else{
		  //set the date for now:
		  aMsg.setCreated(new Date());
	  }

    if (aMsg != null)
    {
      StringBuilder alertMsg = new StringBuilder();
      aMsg.setTitle(getComposeSubject());
      aMsg.setBody(FormattedText.processFormattedText(getComposeBody(), alertMsg));

      aMsg.setAuthor(getAuthorString());
      aMsg.setDraft(Boolean.FALSE);
      aMsg.setApproved(Boolean.FALSE);
      aMsg.setLabel(getSelectedLabel());

      // this property added so can delete forum messages
      // since that and PM share same message object and
      // delete is not null....
      aMsg.setDeleted(Boolean.FALSE);

      // Add the recipientList as String for display in Sent folder
      // Any hidden users will be tacked on at the end
      StringBuffer sendToString = new StringBuffer("");
      StringBuffer sendToHiddenString = new StringBuffer("");

      if (selectedComposeToList.size() == 1) {
          MembershipItem membershipItem = (MembershipItem) courseMemberMap.get(selectedComposeToList.get(0));
          if (membershipItem != null) {
        	  sendToString.append(membershipItem.getName()).append("; ");
          }
      }
      else {
    	  for (int i = 0; i < selectedComposeToList.size(); i++)
    	  {
    		  MembershipItem membershipItem = (MembershipItem) courseMemberMap.get(selectedComposeToList.get(i));
    		  if(membershipItem != null)
    		  {
    			  if (membershipItem.isViewable()) {
    				  sendToString.append(membershipItem.getName()).append("; ");
    			  }
    			  else {
    				  sendToHiddenString.append(membershipItem.getName()).append("; ");
    			  }
    		  }
    	  }
      }

      //add bcc recipients place holder:
      if(selectedComposeBccList.size() > 0 && !sendToString.toString().contains(getResourceBundleString(RECIPIENTS_UNDISCLOSED))){
    	  sendToString.append(getResourceBundleString(RECIPIENTS_UNDISCLOSED)).append("; ");
      }

      //create bcc string to use to display the user's who got BCC'ed
      StringBuffer sendToBccString = new StringBuffer("");
      StringBuffer sendToBccHiddenString = new StringBuffer("");
      for (int i = 0; i < selectedComposeBccList.size(); i++)
      {
    	  MembershipItem membershipItem = (MembershipItem) courseMemberMap.get(selectedComposeBccList.get(i));
    	  if(membershipItem != null)
    	  {
    		  if (membershipItem.isViewable()) {
    			  sendToBccString.append(membershipItem.getName()).append("; ");
    		  }
    		  else {
    			  sendToBccHiddenString.append(membershipItem.getName()).append("; ");
    		  }
    	  }
      }

      if (! "".equals(sendToString.toString())) {
    	  sendToString.delete(sendToString.length()-2, sendToString.length()); //remove last comma and space
      }

      if ("".equals(sendToHiddenString.toString())) {
    	  aMsg.setRecipientsAsText(sendToString.toString());
      }
      else {
    	  sendToHiddenString.delete(sendToHiddenString.length()-2, sendToHiddenString.length()); //remove last comma and space
    	  aMsg.setRecipientsAsText(sendToString.toString() + " " + PrivateMessage.HIDDEN_RECIPIENTS_START + sendToHiddenString.toString() + PrivateMessage.HIDDEN_RECIPIENTS_END);
      }
      //clean up sendToBccString
      if (! "".equals(sendToBccString.toString())) {
    	  sendToBccString.delete(sendToBccString.length()-2, sendToBccString.length()); //remove last comma and space
      }

      if ("".equals(sendToBccHiddenString.toString())) {
    	  aMsg.setRecipientsAsTextBcc(sendToBccString.toString());
      }
      else {
    	  sendToBccHiddenString.delete(sendToBccHiddenString.length()-2, sendToBccHiddenString.length()); //remove last comma and space
    	  aMsg.setRecipientsAsTextBcc(sendToBccString.toString() + " " + PrivateMessage.HIDDEN_RECIPIENTS_START + sendToBccHiddenString.toString() + PrivateMessage.HIDDEN_RECIPIENTS_END);
      }

    }
    //Add attachments
    for(int i=0; i<attachments.size(); i++)
    {
      prtMsgManager.addAttachToPvtMsg(aMsg, ((DecoratedAttachment)attachments.get(i)).getAttachment());
    }
    if(clearAttachments){
    	//clear
    	attachments.clear();
    	oldAttachments.clear();
    }

    return aMsg;
  }
  ///////////////////// Previous/Next topic and message on Detail message page
  /**
   * Set Previous and Next message details with each PrivateMessageDecoratedBean
   */
  public void setPrevNextMessageDetails()
  {
    List tempMsgs = decoratedPvtMsgs;
    for(int i=0; i<tempMsgs.size(); i++)
    {
      PrivateMessageDecoratedBean dmb = (PrivateMessageDecoratedBean)tempMsgs.get(i);
      if(i==0)
      {
        dmb.setHasPre(false);
        if(i==(tempMsgs.size()-1))
        {
            dmb.setHasNext(false);
        }
        else
        {
            dmb.setHasNext(true);
        }
      }
      else if(i==(tempMsgs.size()-1))
      {
        dmb.setHasPre(true);
        dmb.setHasNext(false);
      }
      else
      {
        dmb.setHasNext(true);
        dmb.setHasPre(true);
      }
    }
  }

  /**
   * processDisplayPreviousMsg()
   * Display the previous message from the list of decorated messages
   */
  public String processDisplayPreviousMsg()
  {
    List tempMsgs = getDecoratedPvtMsgs(); // all messages
    int currentMsgPosition = -1;
    if(tempMsgs != null)
    {
      for(int i=0; i<tempMsgs.size(); i++)
      {
        PrivateMessageDecoratedBean thisDmb = (PrivateMessageDecoratedBean)tempMsgs.get(i);
        if(detailMsg.getMsg().getId().equals(thisDmb.getMsg().getId()))
        {
          currentMsgPosition = i;
          break;
        }
      }
    }

    if(currentMsgPosition > 0)
    {
      PrivateMessageDecoratedBean thisDmb = (PrivateMessageDecoratedBean)tempMsgs.get(currentMsgPosition-1);
      PrivateMessage message= (PrivateMessage) prtMsgManager.getMessageById(thisDmb.getMsg().getId());

      detailMsg= new PrivateMessageDecoratedBean(message);
      //get attachments
      prtMsgManager.markMessageAsReadForUser(detailMsg.getMsg());

      PrivateMessage initPrivateMessage = prtMsgManager.initMessageWithAttachmentsAndRecipients(detailMsg.getMsg());
      this.setDetailMsg(new PrivateMessageDecoratedBean(initPrivateMessage));
      setDetailMsgCount++;

      List recLs= initPrivateMessage.getRecipients();
      for (Iterator iterator = recLs.iterator(); iterator.hasNext();)
      {
        PrivateMessageRecipient element = (PrivateMessageRecipient) iterator.next();
        if (element != null)
        {
          if((element.getRead().booleanValue()) || (element.getUserId().equals(getUserId())) )
          {
           getDetailMsg().setHasRead(true) ;
          }
        }
      }
      getDetailMsg().setDepth(thisDmb.getDepth()) ;
      getDetailMsg().setHasNext(thisDmb.getHasNext());
      getDetailMsg().setHasPre(thisDmb.getHasPre()) ;

    }
    LearningResourceStoreService lrss = (LearningResourceStoreService) ComponentManager
            .get("org.sakaiproject.event.api.LearningResourceStoreService");
    Event event = EventTrackingService.newEvent("msgcntr", "read private message", true);
    if (null != lrss) {
    	try{
    		lrss.registerStatement(getStatementForUserReadPvtMsg(lrss.getEventActor(event), getDetailMsg().getMsg().getTitle()), "msgcntr");
    	}catch(Exception e){
    		LOG.error(e.getMessage(), e);
    	}
    }
    return null;
  }

  /**
   * processDisplayNextMsg()
   * Display the Next message from the list of decorated messages
   */
  public String processDisplayNextMsg()
  {
    List tempMsgs = getDecoratedPvtMsgs();
    int currentMsgPosition = -1;
    if(tempMsgs != null)
    {
      for(int i=0; i<tempMsgs.size(); i++)
      {
        PrivateMessageDecoratedBean thisDmb = (PrivateMessageDecoratedBean)tempMsgs.get(i);
        if(detailMsg.getMsg().getId().equals(thisDmb.getMsg().getId()))
        {
          currentMsgPosition = i;
          break;
        }
      }
    }

    if(currentMsgPosition > -2  && currentMsgPosition < (tempMsgs.size()-1))
    {
      PrivateMessageDecoratedBean thisDmb = (PrivateMessageDecoratedBean)tempMsgs.get(currentMsgPosition+1);
      //get attachments
      prtMsgManager.markMessageAsReadForUser(thisDmb.getMsg());

      PrivateMessage initPrivateMessage = prtMsgManager.initMessageWithAttachmentsAndRecipients(thisDmb.getMsg());
      this.setDetailMsg(new PrivateMessageDecoratedBean(initPrivateMessage));
      setDetailMsgCount++;

      List recLs= initPrivateMessage.getRecipients();
      for (Iterator iterator = recLs.iterator(); iterator.hasNext();)
      {
        PrivateMessageRecipient element = (PrivateMessageRecipient) iterator.next();
        if (element != null)
        {
          if((element.getRead().booleanValue()) || (element.getUserId().equals(getUserId())) )
          {
           getDetailMsg().setHasRead(true) ;
          }
        }
      }

      getDetailMsg().setDepth(thisDmb.getDepth()) ;
      getDetailMsg().setHasNext(thisDmb.getHasNext());
      getDetailMsg().setHasPre(thisDmb.getHasPre()) ;
    }
    LearningResourceStoreService lrss = (LearningResourceStoreService) ComponentManager
            .get("org.sakaiproject.event.api.LearningResourceStoreService");
    Event event = EventTrackingService.newEvent("msgcntr", "read private message", true);
    if (null != lrss) {
    	try{
    		lrss.registerStatement(getStatementForUserReadPvtMsg(lrss.getEventActor(event), getDetailMsg().getMsg().getTitle()), "msgcntr");
    	}catch(Exception e){
    		LOG.error(e.getMessage(), e);
    	}
    }
    return null;
  }

  /////////////////////////////////////     DISPLAY NEXT/PREVIOUS TOPIC     //////////////////////////////////
  private PrivateTopicDecoratedBean selectedTopic;

  /**
   * @return Returns the selectedTopic.
   */
  public PrivateTopicDecoratedBean getSelectedTopic()
  {
    return selectedTopic;
  }

  /**
   * @param selectedTopic The selectedTopic to set.
   */
  public void setSelectedTopic(PrivateTopicDecoratedBean selectedTopic)
  {
    this.selectedTopic = selectedTopic;
  }

  /**
   * Add prev and next topic UUID value and booleans for display of links
   *
   */
  public void setPrevNextTopicDetails(String msgNavMode)
  {
    for (int i = 0; i < pvtTopics.size(); i++)
    {
      Topic el = (Topic)pvtTopics.get(i);

      if(el.getTitle().equals(msgNavMode))
      {
        setSelectedTopic(new PrivateTopicDecoratedBean(el)) ;
        if(i ==0)
        {
          getSelectedTopic().setHasPreviousTopic(false);
          if(i==(pvtTopics.size()-1))
          {
            getSelectedTopic().setHasNextTopic(false) ;
          }
          else
          {
            getSelectedTopic().setHasNextTopic(true) ;
            Topic nt=(Topic)pvtTopics.get(i+1);
            if (nt != null)
            {
              //getSelectedTopic().setNextTopicId(nt.getUuid());
              getSelectedTopic().setNextTopicTitle(nt.getTitle());
            }
          }
        }
        else if(i==(pvtTopics.size()-1))
        {
          getSelectedTopic().setHasPreviousTopic(true);
          getSelectedTopic().setHasNextTopic(false) ;

          Topic pt=(Topic)pvtTopics.get(i-1);
          if (pt != null)
          {
            //getSelectedTopic().setPreviousTopicId(pt.getUuid());
            getSelectedTopic().setPreviousTopicTitle(pt.getTitle());
          }
        }
        else
        {
          getSelectedTopic().setHasNextTopic(true) ;
          getSelectedTopic().setHasPreviousTopic(true);

          Topic nt=(Topic)pvtTopics.get(i+1);
          if (nt != null)
          {
            //getSelectedTopic().setNextTopicId(nt.getUuid());
            getSelectedTopic().setNextTopicTitle(nt.getTitle());
          }
          Topic pt=(Topic)pvtTopics.get(i-1);
          if (pt != null)
          {
            //getSelectedTopic().setPreviousTopicId(pt.getUuid());
            getSelectedTopic().setPreviousTopicTitle(pt.getTitle());
          }
        }

      }
    }
    //create a selected topic and set the topic id for next/prev topic
  }
  /**
   * processDisplayPreviousFolder()
   */
  public String processDisplayPreviousTopic() {
	multiDeleteSuccess = false;
    String prevTopicTitle = getExternalParameterByKey("previousTopicTitle");
    if(hasValue(prevTopicTitle))
    {
      msgNavMode=prevTopicTitle;

      decoratedPvtMsgs=new ArrayList() ;

      String typeUuid = getPrivateMessageTypeFromContext(msgNavMode);

      decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_DATE,
          PrivateMessageManager.SORT_DESC);

      decoratedPvtMsgs = createDecoratedDisplay(decoratedPvtMsgs);

      if(selectView!=null && selectView.equalsIgnoreCase(THREADED_VIEW))
      {
      	this.rearrageTopicMsgsThreaded(false);
      }

      //set prev/next Topic
      setPrevNextTopicDetails(msgNavMode);
      //set prev/next message
      setPrevNextMessageDetails();

      if (searchPvtMsgs != null)
      {
    	  searchPvtMsgs.clear();
    	  return DISPLAY_MESSAGES_PG;
      }
    }
    return null;
  }

  /**
   * processDisplayNextFolder()
   */
  public String processDisplayNextTopic()
  {
	multiDeleteSuccess = false;
    String nextTitle = getExternalParameterByKey("nextTopicTitle");
    if(hasValue(nextTitle))
    {
      msgNavMode=nextTitle;
      decoratedPvtMsgs=new ArrayList() ;

      String typeUuid = getPrivateMessageTypeFromContext(msgNavMode);

      decoratedPvtMsgs= prtMsgManager.getMessagesByType(typeUuid, PrivateMessageManager.SORT_COLUMN_DATE,
          PrivateMessageManager.SORT_DESC);

      decoratedPvtMsgs = createDecoratedDisplay(decoratedPvtMsgs);

      if(selectView!=null && selectView.equalsIgnoreCase(THREADED_VIEW))
      {
      	this.rearrageTopicMsgsThreaded(false);
      }

      //set prev/next Topic
      setPrevNextTopicDetails(msgNavMode);
      //set prev/next message
      setPrevNextMessageDetails();

      if (searchPvtMsgs != null)
      {
    	  searchPvtMsgs.clear();
    	  return DISPLAY_MESSAGES_PG;
      }
    }

    return null;
  }
/////////////////////////////////////     DISPLAY NEXT/PREVIOUS TOPIC     //////////////////////////////////

  //////////////////////////////////////////////////////////
  /**
   * @param externalTopicId
   * @return
   */
  private String processDisplayMsgById(String externalMsgId)
  {
    LOG.debug("processDisplayMsgById()");
    String msgId=getExternalParameterByKey(externalMsgId);
    if(msgId!=null)
    {
      PrivateMessageDecoratedBean dbean=null;
      PrivateMessage msg = (PrivateMessage) prtMsgManager.getMessageById(Long.valueOf(msgId)) ;
      if(msg != null)
      {
    	  if (dbean == null)
					throw new IllegalStateException(
							"PrivateMessageDecoratedBean dbean == null!");
        dbean.addPvtMessage(new PrivateMessageDecoratedBean(msg)) ;
        detailMsg = dbean;
      }
    }
    else
    {
      LOG.debug("processDisplayMsgById() - Error");
      return DISPLAY_MESSAGES_PG;
    }
    return SELECTED_MESSAGE_PG;
  }

  //////////////////////REPLY SEND  /////////////////
  public String processPvtMsgPreviewReply(){
	  PrivateMessage pvtMsg = getPvtMsgReplyMessage(getDetailMsg().getMsg(), false);
	  if(pvtMsg == null){
		  return null;
	  }else{
		  PrivateMessageDecoratedBean pmDb = new PrivateMessageDecoratedBean(pvtMsg);
		  pmDb.setIsPreviewReply(true);
		  pmDb.setPreviewReplyTmpMsg(getDetailMsg());
		  this.setDetailMsg(pmDb);

		  return SELECTED_MESSAGE_PG;
	  }
  }
  public String processPvtMsgPreviewReplyBack(){
	  this.setDetailMsg(getDetailMsg().getPreviewReplyTmpMsg());
	  return MESSAGE_REPLY_PG;
  }

  public String processPvtMsgPreviewReplySend(){

	  return processPvtMsgReplySentAction(getDetailMsg().getMsg());
  }

 public String processPvtMsgReplySend() {
    LOG.debug("processPvtMsgReplySend()");

    return processPvtMsgReplySentAction(getPvtMsgReplyMessage(getDetailMsg().getMsg(), false));
 }

 private String processPvtMsgReplySentAction(PrivateMessage rrepMsg){
    if(rrepMsg == null){
    	return null;
    }else{

    	Map<User, Boolean> recipients = getRecipients();

    	prtMsgManager.sendPrivateMessage(rrepMsg, recipients, isSendEmail());

    	if(!rrepMsg.getDraft()){
    		prtMsgManager.markMessageAsRepliedForUser(getReplyingMessage());
    		incrementSynopticToolInfo(recipients.keySet(), false);
    	    LearningResourceStoreService lrss = (LearningResourceStoreService) ComponentManager
    	            .get("org.sakaiproject.event.api.LearningResourceStoreService");
    	    Event event = EventTrackingService.newEvent(DiscussionForumService.EVENT_MESSAGES_RESPONSE, getEventMessage(rrepMsg), false);
    	    EventTrackingService.post(event);
    	    if (null != lrss) {
    	    	try{
    	    		lrss.registerStatement(getStatementForUserSentPvtMsg(lrss.getEventActor(event), getDetailMsg().getMsg().getTitle(), SAKAI_VERB.responded), "msgcntr");
    	    	}catch(Exception e){
    	    		LOG.error(e.getMessage(), e);
    	    	}
    	    }
    	}
    	//reset contents
    	resetComposeContents();

    	return DISPLAY_MESSAGES_PG;
    }
 }

 private PrivateMessage getPvtMsgReplyMessage(PrivateMessage currentMessage, boolean isDraft){
    if (setDetailMsgCount != 1) {
    	setErrorMessage(getResourceBundleString(MULTIPLE_WINDOWS , new Object[] {ServerConfigurationService.getString("ui.service","Sakai")}));
    	return null;
    } else {

    	//PrivateMessage currentMessage = getDetailMsg().getMsg() ;
    	//by default add user who sent original message
    	for (Iterator i = totalComposeToList.iterator(); i.hasNext();) {
    		MembershipItem membershipItem = (MembershipItem) i.next();

    		if (MembershipItem.TYPE_USER.equals(membershipItem.getType())) {
    			if (membershipItem.getUser() != null) {
    				if (membershipItem.getUser().getId().equals(currentMessage.getCreatedBy())) {
    					selectedComposeToList.add(membershipItem.getId());
    				}
    			}
    		}
    	}

    	if(!hasValue(getReplyToSubject()))
    	{
    		if(isDraft){
    			setErrorMessage(getResourceBundleString(MISSING_SUBJECT_DRAFT));
    		}else{
    			setErrorMessage(getResourceBundleString(MISSING_SUBJECT));
    		}
    		return null ;
    	}
    	if(!isDraft){
    		if(selectedComposeToList.size()<1 && selectedComposeBccList.size() < 1)
    		{
    			setErrorMessage(getResourceBundleString(SELECT_RECIPIENT_LIST_FOR_REPLY));
    			return null ;
    		}
    	}

    	PrivateMessage rrepMsg = messageManager.createPrivateMessage() ;

    	StringBuilder alertMsg = new StringBuilder();
    	rrepMsg.setTitle(getReplyToSubject());
    	rrepMsg.setBody(FormattedText.processFormattedText(getReplyToBody(), alertMsg));
    	rrepMsg.setDraft(Boolean.FALSE);
    	rrepMsg.setDeleted(Boolean.FALSE);

    	rrepMsg.setAuthor(getAuthorString());
    	rrepMsg.setApproved(Boolean.FALSE);

    	rrepMsg.setLabel(getSelectedLabel());

    	rrepMsg.setInReplyTo(currentMessage) ;

    	//Add the recipientList as String for display in Sent folder
    	// Since some users may be hidden, if some of these are recipients
    	// filter them out (already checked if no recipients)
    	// if only 1 recipient no need to check visibility
    	StringBuffer sendToString = new StringBuffer("");
    	StringBuffer sendToHiddenString = new StringBuffer("");

    	if (selectedComposeToList.size() == 1) {
    		MembershipItem membershipItem = (MembershipItem) courseMemberMap.get(selectedComposeToList.get(0));
    		if(membershipItem != null)
    		{
    			sendToString.append(membershipItem.getName()).append("; ");
    		}
    	}
    	else {
    		for (int i = 0; i < selectedComposeToList.size(); i++)
    		{
    			MembershipItem membershipItem = (MembershipItem) courseMemberMap.get(selectedComposeToList.get(i));
    			if(membershipItem != null)
    			{
    				if (membershipItem.isViewable()) {
    					sendToString.append(membershipItem.getName()).append("; ");
    				}
    				else {
    					sendToHiddenString.append(membershipItem.getName()).append("; ");
    				}
    			}
    		}
    	}

    	//add bcc recipients place holder:
    	if(selectedComposeBccList.size() > 0 && !sendToString.toString().contains(getResourceBundleString(RECIPIENTS_UNDISCLOSED))){
    		sendToString.append(getResourceBundleString(RECIPIENTS_UNDISCLOSED)).append("; ");
    	}

    	//create sendToBccString
    	StringBuffer sendToBccString = new StringBuffer("");
    	StringBuffer sendToBccHiddenString = new StringBuffer("");
    	for (int i = 0; i < selectedComposeBccList.size(); i++)
    	{
    		MembershipItem membershipItem = (MembershipItem) courseMemberMap.get(selectedComposeBccList.get(i));
    		if(membershipItem != null)
    		{
    			if (membershipItem.isViewable()) {
    				sendToBccString.append(membershipItem.getName()).append("; ");
    			}
    			else {
    				sendToBccHiddenString.append(membershipItem.getName()).append("; ");
    			}
    		}
    	}

    	//clean sendToString
    	if (! "".equals(sendToString.toString())) {
    		sendToString.delete(sendToString.length()-2, sendToString.length()); //remove last comma and space
    	}

    	if ("".equals(sendToHiddenString.toString())) {
    		rrepMsg.setRecipientsAsText(sendToString.toString());
    	}
    	else {
    		sendToHiddenString.delete(sendToHiddenString.length()-2, sendToHiddenString.length()); //remove last comma and space
    		rrepMsg.setRecipientsAsText(sendToString.toString() + " " + PrivateMessage.HIDDEN_RECIPIENTS_START + sendToHiddenString.toString() + PrivateMessage.HIDDEN_RECIPIENTS_END);
    	}

    	//clean sendToBccString
    	//clean sendToString
    	if (! "".equals(sendToBccString.toString())) {
    		sendToBccString.delete(sendToBccString.length()-2, sendToBccString.length()); //remove last comma and space
    	}

    	if ("".equals(sendToBccHiddenString.toString())) {
    		rrepMsg.setRecipientsAsTextBcc(sendToBccString.toString());
    	}
    	else {
    		sendToBccHiddenString.delete(sendToBccHiddenString.length()-2, sendToBccHiddenString.length()); //remove last comma and space
    		rrepMsg.setRecipientsAsTextBcc(sendToBccString.toString() + " " + PrivateMessage.HIDDEN_RECIPIENTS_START + sendToBccHiddenString.toString() + PrivateMessage.HIDDEN_RECIPIENTS_END);
    	}

    	//Add attachments
    	for(int i=0; i<allAttachments.size(); i++)
    	{
    		prtMsgManager.addAttachToPvtMsg(rrepMsg, ((DecoratedAttachment)allAttachments.get(i)).getAttachment());
    	}

    	return rrepMsg;

    }
  }

  // ////////////////////Forward SEND /////////////////

 public String processPvtMsgPreviewForward(){
	 PrivateMessage pvtMsg = getPvtMsgForward(getDetailMsg().getMsg(), false);
	 if(pvtMsg == null){
		 return null;
	 }else{
		 PrivateMessageDecoratedBean pmDb = new PrivateMessageDecoratedBean(pvtMsg);
		 pmDb.setIsPreviewForward(true);
		 pmDb.setPreviewReplyTmpMsg(getDetailMsg());
		 this.setDetailMsg(pmDb);

		 return SELECTED_MESSAGE_PG;
	 }
 }
 public String processPvtMsgPreviewForwardBack(){
	 String title = getDetailMsg().getMsg().getTitle();
	 String body = getDetailMsg().getMsg().getBody();
	 this.setDetailMsg(getDetailMsg().getPreviewReplyTmpMsg());
	 String returnString =  processPvtMsgForward();
	 //reset title and body:
	 getDetailMsg().getMsg().setTitle(title);
	 setForwardSubject(title);
	 getDetailMsg().getMsg().setBody(body);
	 setForwardBody(body);

	 return returnString;
 }

 public String processPvtMsgPreviewForwardSend(){
	  processPvtMsgForwardSendHelper(getDetailMsg().getMsg());
	  return DISPLAY_MESSAGES_PG;
 }
 public String processPvtMsgForwardSend() {
    LOG.debug("processPvtMsgForwardSend()");
    if (setDetailMsgCount != 1) {
    	setErrorMessage(getResourceBundleString(MULTIPLE_WINDOWS , new Object[] {ServerConfigurationService.getString("ui.service","Sakai")}));
    	return null;
    } else {
    	PrivateMessage pvtMsg = getPvtMsgForward(getDetailMsg().getMsg(), false);
    	if(pvtMsg == null){
    		return null;
    	}else{
    		processPvtMsgForwardSendHelper(pvtMsg);
    		return DISPLAY_MESSAGES_PG;
    	}
    }
 }

 public String processPvtMsgForwardSaveDraft(){
	 LOG.debug("processPvtMsgForwardSaveDraft()");
	 if (setDetailMsgCount != 1) {
	     setErrorMessage(getResourceBundleString(MULTIPLE_WINDOWS , new Object[] {ServerConfigurationService.getString("ui.service","Sakai")}));
		 return null;
	 } else {
		 PrivateMessage pvtMsg = getPvtMsgForward(getDetailMsg().getMsg(), true);
		 if(pvtMsg == null){
			 return null;
		 }else{
			 pvtMsg.setDraft(Boolean.TRUE);
			 processPvtMsgForwardSendHelper(pvtMsg);
			 return returnDraftPage();
		 }
	 }
 }

 private PrivateMessage getPvtMsgForward(PrivateMessage currentMessage, boolean isDraft){

	 if(!isDraft){
		 if(getSelectedComposeToList().size()<1 && getSelectedComposeBccList().size() < 1)
		 {
			 setErrorMessage(getResourceBundleString(SELECT_MSG_RECIPIENT));
			 return null ;
		 }
	 }
	 if(!hasValue(getForwardSubject()))
	 {
		 if(isDraft){
			 setErrorMessage(getResourceBundleString(MISSING_SUBJECT_DRAFT));
		 }else{
			 setErrorMessage(getResourceBundleString(MISSING_SUBJECT));
		 }
		 return null ;
	 }

    	PrivateMessage rrepMsg = messageManager.createPrivateMessage() ;

    	StringBuilder alertMsg = new StringBuilder();
    	rrepMsg.setTitle(getForwardSubject());
    	rrepMsg.setDraft(Boolean.FALSE);
    	rrepMsg.setDeleted(Boolean.FALSE);

    	rrepMsg.setAuthor(getAuthorString());
    	rrepMsg.setApproved(Boolean.FALSE);
    	rrepMsg.setBody(FormattedText.processFormattedText(getForwardBody(), alertMsg));

    	rrepMsg.setLabel(getSelectedLabel());

    	rrepMsg.setInReplyTo(currentMessage) ;

    	//Add the recipientList as String for display in Sent folder
    	// Since some users may be hidden, if some of these are recipients
    	// filter them out (already checked if no recipients)
    	// if only 1 recipient no need to check visibility
    	StringBuffer sendToString = new StringBuffer();
    	StringBuffer sendToHiddenString = new StringBuffer();

    	if (selectedComposeToList.size() == 1) {
    		MembershipItem membershipItem = (MembershipItem) courseMemberMap.get(selectedComposeToList.get(0));
    		if(membershipItem != null)
    		{
    			sendToString.append(membershipItem.getName()).append("; ");
    		}
    	}
    	else {
    		for (int i = 0; i < selectedComposeToList.size(); i++)
    		{
    			MembershipItem membershipItem = (MembershipItem) courseMemberMap.get(selectedComposeToList.get(i));
    			if(membershipItem != null)
    			{
    				if (membershipItem.isViewable()) {
    					sendToString.append(membershipItem.getName()).append("; ");
    				}
    				else {
    					sendToHiddenString.append(membershipItem.getName()).append("; ");
    				}
    			}
    		}
    	}

    	//add bcc recipients place holder:
    	if(selectedComposeBccList.size() > 0 && !sendToString.toString().contains(getResourceBundleString(RECIPIENTS_UNDISCLOSED))){
    		sendToString.append(getResourceBundleString(RECIPIENTS_UNDISCLOSED)).append("; ");
    	}

    	StringBuffer sendToBccString = new StringBuffer();
    	StringBuffer sendToBccHiddenString = new StringBuffer();
    	for (int i = 0; i < selectedComposeBccList.size(); i++)
    	{
    		MembershipItem membershipItem = (MembershipItem) courseMemberMap.get(selectedComposeBccList.get(i));
    		if(membershipItem != null)
    		{
    			if (membershipItem.isViewable()) {
    				sendToBccString.append(membershipItem.getName()).append("; ");
    			}
    			else {
    				sendToBccHiddenString.append(membershipItem.getName()).append("; ");
    			}
    		}
    	}

    	//clean sendToString
    	if (! "".equals(sendToString.toString())) {
    		sendToString.delete(sendToString.length()-2, sendToString.length()); //remove last comma and space
    	}

    	if ("".equals(sendToHiddenString.toString())) {
    		rrepMsg.setRecipientsAsText(sendToString.toString());
    	}
    	else {
    		sendToHiddenString.delete(sendToHiddenString.length()-2, sendToHiddenString.length()); //remove last comma and space
    		rrepMsg.setRecipientsAsText(sendToString.toString() + " (" + sendToHiddenString.toString() + ")");
    	}

    	//clean sendToBccString
    	if (! "".equals(sendToBccString.toString())) {
    		sendToBccString.delete(sendToBccString.length()-2, sendToBccString.length()); //remove last comma and space
    	}

    	if ("".equals(sendToBccHiddenString.toString())) {
    		rrepMsg.setRecipientsAsTextBcc(sendToBccString.toString());
    	}
    	else {
    		sendToBccHiddenString.delete(sendToBccHiddenString.length()-2, sendToBccHiddenString.length()); //remove last comma and space
    		rrepMsg.setRecipientsAsTextBcc(sendToBccString.toString() + " (" + sendToBccHiddenString.toString() + ")");
    	}

    	//Add attachments
    	for(int i=0; i<allAttachments.size(); i++)
    	{
    		prtMsgManager.addAttachToPvtMsg(rrepMsg, ((DecoratedAttachment)allAttachments.get(i)).getAttachment());
    	}

    	return rrepMsg;
    }

    private void processPvtMsgForwardSendHelper(PrivateMessage rrepMsg){
    	Map<User, Boolean> recipients = getRecipients();

    	prtMsgManager.sendPrivateMessage(rrepMsg, recipients, isSendEmail());

    	if(!rrepMsg.getDraft()){
    		//update Synoptic tool info
    		incrementSynopticToolInfo(recipients.keySet(), false);
            LearningResourceStoreService lrss = (LearningResourceStoreService) ComponentManager
                    .get("org.sakaiproject.event.api.LearningResourceStoreService");
            Event event = EventTrackingService.newEvent(DiscussionForumService.EVENT_MESSAGES_FORWARD, getEventMessage(rrepMsg), false);
            EventTrackingService.post(event);
            if (null != lrss) {
            	try{
            		lrss.registerStatement(getStatementForUserSentPvtMsg(lrss.getEventActor(event), getDetailMsg().getMsg().getTitle(), SAKAI_VERB.responded), "msgcntr");
            	}catch(Exception e){
            		LOG.error(e.getMessage(), e);
            	}
            }
    	}
    	//reset contents
    	resetComposeContents();
    }

  //reply all preview:
 public String processPvtMsgPreviewReplyAll(){
	 PrivateMessage pvtMsg = processPvtMsgReplyAllSendHelper(true, Boolean.FALSE);
	 if(pvtMsg == null){
		 return null;
	 }else{
		 PrivateMessageDecoratedBean pmDb = new PrivateMessageDecoratedBean(pvtMsg);
		 pmDb.setIsPreviewReplyAll(true);
		 pmDb.setPreviewReplyTmpMsg(getDetailMsg());
		 this.setDetailMsg(pmDb);

		 return SELECTED_MESSAGE_PG;
	 }
 }
 public String processPvtMsgPreviewReplyAllBack(){
	  this.setDetailMsg(getDetailMsg().getPreviewReplyTmpMsg());
	  return MESSAGE_ReplyAll_PG;
 }

 public String processPvtMsgPreviewReplyAllSend(){
	 this.setDetailMsg(getDetailMsg().getPreviewReplyTmpMsg());
	 PrivateMessage pvtMsg = processPvtMsgReplyAllSendHelper(false, Boolean.FALSE);
	 if(pvtMsg == null){
		 return null;
	 }else{
		 return DISPLAY_MESSAGES_PG;
	 }
 }

 public String processPvtMsgReplyAllSaveDraft(){
	 LOG.debug("processPvtMsgReply All Send()");
	 if (setDetailMsgCount != 1) {
	     setErrorMessage(getResourceBundleString(MULTIPLE_WINDOWS , new Object[] {ServerConfigurationService.getString("ui.service","Sakai")}));
		 return null;
	 } else {
		 PrivateMessage pvtMsg = processPvtMsgReplyAllSendHelper(false, Boolean.TRUE);
		 if(pvtMsg == null){
			 return null;
		 }else{
			 return returnDraftPage();
		 }
	 }
 }

  public String processPvtMsgReplyAllSend() {
    LOG.debug("processPvtMsgReply All Send()");
    if (setDetailMsgCount != 1) {
    	setErrorMessage(getResourceBundleString(MULTIPLE_WINDOWS , new Object[] {ServerConfigurationService.getString("ui.service","Sakai")}));
    	return null;
    } else {
    	PrivateMessage pvtMsg = processPvtMsgReplyAllSendHelper(false, Boolean.FALSE);
    	if(pvtMsg == null){
    		return null;
    	}else{
    		return DISPLAY_MESSAGES_PG;
    	}
    }
  }

  private PrivateMessage processPvtMsgReplyAllSendHelper(boolean preview, Boolean isDraft){

	  PrivateMessage currentMessage = getDetailMsg().getMsg() ;

	  String msgauther=currentMessage.getAuthor();//string   "Test"

	  //Select Forward Recipients

	  if(!hasValue(getForwardSubject()))
	  {
		  if(isDraft){
			  setErrorMessage(getResourceBundleString(MISSING_SUBJECT_DRAFT));
		  }else{
			  setErrorMessage(getResourceBundleString(MISSING_SUBJECT));
		  }
		  return null ;
	  }

	  PrivateMessage rrepMsg = messageManager.createPrivateMessage() ;

	  StringBuilder alertMsg = new StringBuilder();
	  rrepMsg.setTitle(getForwardSubject());
	  rrepMsg.setDraft(isDraft);
	  rrepMsg.setDeleted(Boolean.FALSE);

	  rrepMsg.setAuthor(getAuthorString());
	  rrepMsg.setApproved(Boolean.FALSE);
	  //add some emty space to the msg composite, by huxt
	  String replyAllbody="  ";
	  replyAllbody=getForwardBody();

	  rrepMsg.setBody(FormattedText.processFormattedText(replyAllbody, alertMsg));
	  rrepMsg.setLabel(getSelectedLabel());
	  rrepMsg.setInReplyTo(currentMessage) ;

	  //Add attachments
	  for(int i=0; i<allAttachments.size(); i++)
	  {
		  prtMsgManager.addAttachToPvtMsg(rrepMsg, ((DecoratedAttachment)allAttachments.get(i)).getAttachment());
	  }

	  User autheruser=null;
	  try {
		  autheruser = UserDirectoryService.getUser(currentMessage.getCreatedBy());
	  } catch (UserNotDefinedException e) {
		  e.printStackTrace();
	  }

	  List tmpRecipList = currentMessage.getRecipients();

	  Map<User, Boolean> returnSet = new HashMap<User, Boolean>();
	  StringBuffer sendToStringreplyall = new StringBuffer();

	  Iterator iter = tmpRecipList.iterator();
	  while (iter.hasNext())
	  {
		  PrivateMessageRecipient tmpPMR = (PrivateMessageRecipient)iter.next();
		  User replyrecipientaddtmp=null;
		  try {
			  replyrecipientaddtmp = UserDirectoryService.getUser(tmpPMR.getUserId());
		  } catch (UserNotDefinedException e) {
			  // TODO Auto-generated catch block
			  LOG.warn("Unable to find user : " + tmpPMR.getUserId(), e);
		  }

		  if (replyrecipientaddtmp == null){
			  LOG.warn("continuing passed user : "+tmpPMR.getUserId());
			  //throw new IllegalStateException("User replyrecipientaddtmp == null!");
		  }else{
		  	if(!(replyrecipientaddtmp.getDisplayName()).equals(getUserName()) && !tmpPMR.getBcc())//&&(!(replyrecipientaddtmp.getDisplayName()).equals(msgauther)))
		  	{
				  returnSet.put(replyrecipientaddtmp, tmpPMR.getBcc());
		        }
		  }
	  }

	  if(currentMessage.getRecipientsAsText() != null && !"".equals(currentMessage.getRecipientsAsText())){
		  sendToStringreplyall.append(currentMessage.getRecipientsAsText()).append("; ");
	  }
	  if(returnSet.isEmpty()) {
		  returnSet.put(autheruser, false);
		  if(!sendToStringreplyall.toString().contains(msgauther)){
			  //only add it to the reply string if it doesn't exist
			  sendToStringreplyall.append(msgauther).append("; ");
		  }
	  }
	  if(returnSet.containsKey(autheruser) && !sendToStringreplyall.toString().contains(msgauther)){
		  sendToStringreplyall.append(msgauther).append("; ");
	  }

	  //Add the recipientList as String for display in Sent folder
	  // Since some users may be hidden, if some of these are recipients
	  // filter them out (already checked if no recipients)
	  // if only 1 recipient no need to check visibility
	  StringBuffer sendToString = new StringBuffer(sendToStringreplyall);
	  StringBuffer sendToHiddenString = new StringBuffer();

	  if (selectedComposeToList.size() == 1) {
		  MembershipItem membershipItem = (MembershipItem) courseMemberMap.get(selectedComposeToList.get(0));
		  if(membershipItem != null)
		  {
			  sendToString.append(membershipItem.getName()).append("; ");
		  }
	  }
	  else {
		  for (int i = 0; i < selectedComposeToList.size(); i++)
		  {
			  MembershipItem membershipItem = (MembershipItem) courseMemberMap.get(selectedComposeToList.get(i));
			  if(membershipItem != null)
			  {
				  if(!sendToStringreplyall.toString().contains(membershipItem.getName())){
					  if (membershipItem.isViewable()) {
						  sendToString.append(membershipItem.getName()).append("; ");
					  }
					  else {
						  sendToHiddenString.append(membershipItem.getName()).append("; ");
					  }
				  }
			  }
		  }
	  }

	  //add bcc recipients place holder:
	  if(selectedComposeBccList.size() > 0 && !sendToString.toString().contains(getResourceBundleString(RECIPIENTS_UNDISCLOSED))){
		  sendToString.append(getResourceBundleString(RECIPIENTS_UNDISCLOSED)).append("; ");
	  }

	  //create sendToBccString
	  StringBuffer sendToBccString = new StringBuffer();
	  StringBuffer sendToBccHiddenString = new StringBuffer();
	  for (int i = 0; i < selectedComposeBccList.size(); i++)
	  {
		  MembershipItem membershipItem = (MembershipItem) courseMemberMap.get(selectedComposeBccList.get(i));
		  if(membershipItem != null)
		  {
			  if (membershipItem.isViewable()) {
				  sendToBccString.append(membershipItem.getName()).append("; ");
			  }
			  else {
				  sendToBccHiddenString.append(membershipItem.getName()).append("; ");
			  }
		  }
	  }

	  //clean sendToString
	  if (! "".equals(sendToString.toString()) && sendToString.length() >= 2) {
		  sendToString.delete(sendToString.length()-2, sendToString.length()); //remove last comma and space
	  }

	  if ("".equals(sendToHiddenString.toString())) {
		  rrepMsg.setRecipientsAsText(sendToString.toString());
	  }
	  else {
		  sendToHiddenString.delete(sendToHiddenString.length()-2, sendToHiddenString.length()); //remove last comma and space
		  rrepMsg.setRecipientsAsText(sendToString.toString() + " (" + sendToHiddenString.toString() + ")");
	  }

	  //clean sendToBccString
	  if (! "".equals(sendToBccString.toString()) && sendToBccString.length() >= 2) {
		  sendToBccString.delete(sendToBccString.length()-2, sendToBccString.length()); //remove last comma and space
	  }

	  if ("".equals(sendToBccHiddenString.toString())) {
		  rrepMsg.setRecipientsAsTextBcc(sendToBccString.toString());
	  }
	  else {
		  sendToBccHiddenString.delete(sendToBccHiddenString.length()-2, sendToBccHiddenString.length()); //remove last comma and space
		  rrepMsg.setRecipientsAsTextBcc(sendToBccString.toString() + " (" + sendToBccHiddenString.toString() + ")");
	  }

	  //Add selected users to reply all list

	  Map<User, Boolean> recipients = getRecipients();
	  for (Iterator<Entry<User, Boolean>> i = recipients.entrySet().iterator(); i.hasNext();){
		  Entry<User, Boolean> entrySet = (Entry<User, Boolean>) i.next();
		  if(!returnSet.containsKey(entrySet.getKey())){
			  returnSet.put(entrySet.getKey(), entrySet.getValue());
		  }
	  }
	  if(!preview){
	          prtMsgManager.sendPrivateMessage(rrepMsg, returnSet, isSendEmail());

		  if(!rrepMsg.getDraft()){
			  prtMsgManager.markMessageAsRepliedForUser(getReplyingMessage());
			  //update Synoptic tool info
			  incrementSynopticToolInfo(returnSet.keySet(), false);
	          LearningResourceStoreService lrss = (LearningResourceStoreService) ComponentManager
	                    .get("org.sakaiproject.event.api.LearningResourceStoreService");
	          Event event = EventTrackingService.newEvent(DiscussionForumService.EVENT_MESSAGES_FORWARD, getEventMessage(rrepMsg), false);
	          EventTrackingService.post(event);
	          if (null != lrss) {
	        	  try{
	        		  lrss.registerStatement(getStatementForUserSentPvtMsg(lrss.getEventActor(event), getDetailMsg().getMsg().getTitle(), SAKAI_VERB.responded), "msgcntr");
	        	  }catch(Exception e){
	          		LOG.error(e.getMessage(), e);
	        	  }
	          }
		  }
		  //reset contents
		  resetComposeContents();
	  }
	  return rrepMsg;
  }

 private boolean containedInList(User user,List list){

	boolean isContain=false;
	 if (list==null)
	 {
		 return false;
	 }

	 Iterator iter = list.iterator();

	   User tmpuser=null;
	   while(iter.hasNext()){

			 PrivateMessageRecipient tmpPMR = (PrivateMessageRecipient)iter.next();
		 	User replyrecipientaddtmp=null;
				try {
					replyrecipientaddtmp = UserDirectoryService.getUser(tmpPMR.getUserId());
				} catch (UserNotDefinedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

		   if((replyrecipientaddtmp!=null)&&(replyrecipientaddtmp==user)){
			   //tmplist.add(tmpPMR);
			   isContain=true;

		   }
	   }
	   return isContain;

  }

  /**
   * process from Compose screen
   * @return - pvtMsg
   */
 public String processPvtMsgReplySaveDraft() {
	 PrivateMessage pvtMsg = getPvtMsgReplyMessage(getDetailMsg().getMsg(), true);
	 if(pvtMsg == null){
		 return null;
	 }else{
		 pvtMsg.setDraft(Boolean.TRUE);
		 setMsgNavMode(PVTMSG_MODE_DRAFT);
		 String returnVal = processPvtMsgReplySentAction(pvtMsg);
		 if(returnVal == null){
			 return null;
		 }else{
			 return returnDraftPage();
		 }
	 }
 }

  ////////////////////////////////////////////////////////////////
  public String processPvtMsgEmptyDelete() {
    LOG.debug("processPvtMsgEmptyDelete()");

    List delSelLs=new ArrayList() ;
    //this.setDisplayPvtMsgs(getDisplayPvtMsgs());
    for (Iterator iter = this.decoratedPvtMsgs.iterator(); iter.hasNext();)
    {
      PrivateMessageDecoratedBean element = (PrivateMessageDecoratedBean) iter.next();
      if(element.getIsSelected())
      {
        delSelLs.add(element);
      }
    }
    this.setSelectedDeleteItems(delSelLs);
    if(delSelLs.size()<1)
    {
      setErrorMessage(getResourceBundleString(SELECT_MSGS_TO_DELETE));
      return null;  //stay in the same page if nothing is selected for delete
    }else {
      setErrorMessage(getResourceBundleString(CONFIRM_PERM_MSG_DELETE));
      return DELETE_MESSAGE_PG;
    }
  }

  //delete private message
  public String processPvtMsgMultiDelete()
  {
    LOG.debug("processPvtMsgMultiDelete()");

    boolean deleted = false;
    for (Iterator iter = getSelectedDeleteItems().iterator(); iter.hasNext();)
    {
      PrivateMessage element = ((PrivateMessageDecoratedBean) iter.next()).getMsg();
      if (element != null)
      {
    	deleted = true;
        prtMsgManager.deletePrivateMessage(element, getPrivateMessageTypeFromContext(msgNavMode)) ;
      }

      if ("pvt_deleted".equals(msgNavMode))
    	  EventTrackingService.post(EventTrackingService.newEvent(DiscussionForumService.EVENT_MESSAGES_REMOVE, getEventMessage((Message) element), false));
      else
    	  EventTrackingService.post(EventTrackingService.newEvent(DiscussionForumService.EVENT_MESSAGES_MOVE_TO_DELETED_FOLDER, getEventMessage((Message) element), false));

    }

    if (deleted)
    {
    	if ("pvt_deleted".equals(msgNavMode))
    		multiDeleteSuccessMsg = getResourceBundleString(PERM_DELETE_SUCCESS_MSG);
    	else
    		multiDeleteSuccessMsg = getResourceBundleString(MULTIDELETE_SUCCESS_MSG);

    	multiDeleteSuccess = true;
    }

	return DISPLAY_MESSAGES_PG;
  }

  public String processPvtMsgDispOtions()
  {
    LOG.debug("processPvtMsgDispOptions()");

    return "pvtMsgOrganize" ;
  }

  ///////////////////////////       Process Select All       ///////////////////////////////
  private boolean selectAll = false;
  private int numberChecked = 0; // to cover case where user selectes check all

  public boolean isSelectAll()
  {
    return selectAll;
  }
  public void setSelectAll(boolean selectAll)
  {
    this.selectAll = selectAll;
  }

  public int getNumberChecked()
  {
	return numberChecked;
  }

  /**
   * process isSelected for all decorated messages
   * @return same page i.e. will be pvtMsg
   */
  public String processCheckAll()
  {
    LOG.debug("processCheckAll()");
    selectAll= true;
    multiDeleteSuccess = false;

    return null;
  }

  //////////////////////////////   ATTACHMENT PROCESSING        //////////////////////////
  private ArrayList attachments = new ArrayList();

  private String removeAttachId = null;
  private ArrayList prepareRemoveAttach = new ArrayList();
  private boolean attachCaneled = false;
  private ArrayList oldAttachments = new ArrayList();
  private List allAttachments = new ArrayList();

  public ArrayList getAttachments()
  {
    ToolSession session = SessionManager.getCurrentToolSession();
    if (session.getAttribute(FilePickerHelper.FILE_PICKER_CANCEL) == null &&
        session.getAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS) != null)
    {
      List refs = (List)session.getAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS);
      if(refs != null && refs.size()>0)
      {
        Reference ref = (Reference)refs.get(0);

        for(int i=0; i<refs.size(); i++)
        {
          ref = (Reference) refs.get(i);
          Attachment thisAttach = prtMsgManager.createPvtMsgAttachment(
              ref.getId(), ref.getProperties().getProperty(ref.getProperties().getNamePropDisplayName()));

          //TODO - remove this as being set for test only
          //thisAttach.setPvtMsgAttachId(Long.valueOf(1));

          attachments.add(new DecoratedAttachment(thisAttach));

        }
      }
    }
    session.removeAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS);
    session.removeAttribute(FilePickerHelper.FILE_PICKER_CANCEL);

    return attachments;
  }

  public List getAllAttachments()
  {
    ToolSession session = SessionManager.getCurrentToolSession();
    if (session.getAttribute(FilePickerHelper.FILE_PICKER_CANCEL) == null &&
        session.getAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS) != null)
    {
      List refs = (List)session.getAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS);
      if(refs != null && refs.size()>0)
      {
        Reference ref = (Reference)refs.get(0);

        for(int i=0; i<refs.size(); i++)
        {
          ref = (Reference) refs.get(i);
          Attachment thisAttach = prtMsgManager.createPvtMsgAttachment(
              ref.getId(), ref.getProperties().getProperty(ref.getProperties().getNamePropDisplayName()));

          //TODO - remove this as being set for test only
          //thisAttach.setPvtMsgAttachId(Long.valueOf(1));
          allAttachments.add(new DecoratedAttachment(thisAttach));
        }
      }
    }
    session.removeAttribute(FilePickerHelper.FILE_PICKER_ATTACHMENTS);
    session.removeAttribute(FilePickerHelper.FILE_PICKER_CANCEL);

//    if( allAttachments == null || (allAttachments.size()<1))
//    {
//      allAttachments.addAll(this.getDetailMsg().getMsg().getAttachments()) ;
//    }
    return allAttachments;
  }

  public void setAttachments(ArrayList attachments)
  {
    this.attachments = attachments;
  }

  public String getRemoveAttachId()
  {
    return removeAttachId;
  }

  public final void setRemoveAttachId(String removeAttachId)
  {
    this.removeAttachId = removeAttachId;
  }

  public ArrayList getPrepareRemoveAttach()
  {
    if((removeAttachId != null) && (!"".equals(removeAttachId)))
    {
      prepareRemoveAttach.add(prtMsgManager.getPvtMsgAttachment(Long.valueOf(removeAttachId)));
    }

    return prepareRemoveAttach;
  }

  public final void setPrepareRemoveAttach(ArrayList prepareRemoveAttach)
  {
    this.prepareRemoveAttach = prepareRemoveAttach;
  }

  //Redirect to File picker
  public String processAddAttachmentRedirect()
  {
    LOG.debug("processAddAttachmentRedirect()");
    try
    {
      ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
      context.redirect("sakai.filepicker.helper/tool");
      return null;
    }
    catch(Exception e)
    {
      LOG.debug("processAddAttachmentRedirect() - Exception");
      return null;
    }
  }

  //Process remove attachment
  public String processDeleteAttach()
  {
    LOG.debug("processDeleteAttach()");

    ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
    String attachId = null;

    Map paramMap = context.getRequestParameterMap();
    Iterator<Entry<Object, String>> itr = paramMap.entrySet().iterator();
    while(itr.hasNext())
    {
      Entry<Object, String> entry = itr.next();
    	Object key = entry.getKey();
      if( key instanceof String)
      {
        String name =  (String)key;
        int pos = name.lastIndexOf("pvmsg_current_attach");

        if(pos>=0 && name.length()==pos+"pvmsg_current_attach".length())
        {
          attachId = entry.getValue();
          break;
        }
      }
    }

    if ((attachId != null) && (!"".equals(attachId)))
    {
      for (int i = 0; i < attachments.size(); i++)
      {
        if (attachId.equalsIgnoreCase(((DecoratedAttachment) attachments.get(i)).getAttachment()
            .getAttachmentId()))
        {
          attachments.remove(i);
          break;
        }
      }
    }

    return null ;
  }

  //Process remove attachments from reply message
  public String processDeleteReplyAttach()
  {
    LOG.debug("processDeleteReplyAttach()");

    ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
    String attachId = null;

    Map paramMap = context.getRequestParameterMap();
    Iterator<Entry<Object, String>> itr = paramMap.entrySet().iterator();
    while(itr.hasNext())
    {
      Entry<Object, String> entry = itr.next();
      Object key = entry.getKey();
      if( key instanceof String)
      {
        String name =  (String)key;
        int pos = name.lastIndexOf("remsg_current_attach");

        if(pos>=0 && name.length()==pos+"remsg_current_attach".length())
        {
          attachId = entry.getValue();
          break;
        }
      }
    }

    if ((attachId != null) && (!"".equals(attachId)))
    {
      for (int i = 0; i < allAttachments.size(); i++)
      {
        if (attachId.equalsIgnoreCase(((DecoratedAttachment) allAttachments.get(i)).getAttachment()
            .getAttachmentId()))
        {
          allAttachments.remove(i);
          break;
        }
      }
    }

    return null ;
  }

  //process deleting confirm from separate screen
  public String processRemoveAttach()
  {
    LOG.debug("processRemoveAttach()");

    try
    {
      Attachment sa = prtMsgManager.getPvtMsgAttachment(Long.valueOf(removeAttachId));
      String id = sa.getAttachmentId();

      for(int i=0; i<attachments.size(); i++)
      {
      	DecoratedAttachment thisAttach = (DecoratedAttachment)attachments.get(i);
        if(((Long)thisAttach.getAttachment().getPvtMsgAttachId()).toString().equals(removeAttachId))
        {
          attachments.remove(i);
          break;
        }
      }

      prtMsgManager.removePvtMsgAttachment(sa);
      if(id.toLowerCase().startsWith("/attachment"))
        contentHostingService.removeResource(id);
    }
    catch(Exception e)
    {
      LOG.debug("processRemoveAttach() - Exception");
    }

    removeAttachId = null;
    prepareRemoveAttach.clear();
    return COMPOSE_MSG_PG;

  }

  public String processRemoveAttachCancel()
  {
    LOG.debug("processRemoveAttachCancel()");

    removeAttachId = null;
    prepareRemoveAttach.clear();
    return COMPOSE_MSG_PG ;
  }

  ////////////  SETTINGS        //////////////////////////////
  //Setting Getter and Setter
  public String getActivatePvtMsg()
  {
    return activatePvtMsg;
  }
  public void setActivatePvtMsg(String activatePvtMsg)
  {
    this.activatePvtMsg = activatePvtMsg;
  }
  public String getForwardPvtMsg()
  {
    return forwardPvtMsg;
  }
  public void setForwardPvtMsg(String forwardPvtMsg)
  {
    this.forwardPvtMsg = forwardPvtMsg;
  }
  public String getForwardPvtMsgEmail()
  {
    return forwardPvtMsgEmail;
  }
  public void setForwardPvtMsgEmail(String forwardPvtMsgEmail)
  {
    this.forwardPvtMsgEmail = forwardPvtMsgEmail;
  }

  public String getSendToEmail() {
      return this.sendToEmail;
  }
  public void setSendToEmail(String sendToEmail) {
      this.sendToEmail = sendToEmail;
  }

  public boolean getSuperUser()
  {
    superUser=SecurityService.isSuperUser();
    return superUser;
  }
  //is instructor
  public boolean isInstructor()
  {
    return prtMsgManager.isInstructor();
  }

  public boolean isEmailPermit() {
	  return prtMsgManager.isEmailPermit();
  }

  public void setSuperUser(boolean superUser)
  {
    this.superUser = superUser;
  }

  public String processPvtMsgOrganize()
  {
    LOG.debug("processPvtMsgOrganize()");
    return null ;
    //return "pvtMsgOrganize";
  }

  public String processPvtMsgStatistics()
  {
    LOG.debug("processPvtMsgStatistics()");

    return null ;
    //return "pvtMsgStatistics";
  }

  public String processPvtMsgSettings()
  {
    LOG.debug("processPvtMsgSettings()");
    return MESSAGE_SETTING_PG;
  }

  public void processPvtMsgSettingsRevise(ValueChangeEvent event)
  {
    LOG.debug("processPvtMsgSettingsRevise()");

    /** block executes when changing value to "no" */
    if (SET_AS_YES.equals(forwardPvtMsg)){
      setForwardPvtMsgEmail(null);
    }
    if (SET_AS_NO.equals(forwardPvtMsg)){
      setValidEmail(true);
    }
  }

  public String processPvtMsgSettingsSave()
  {
    LOG.debug("processPvtMsgSettingsSave()");

    String email= getForwardPvtMsgEmail();
    String activate=getActivatePvtMsg() ;
    String forward=getForwardPvtMsg() ;
    if (email != null && (!SET_AS_NO.equals(forward))
            && !EmailValidator.getInstance().isValid(email) ) {
      setValidEmail(false);
      setErrorMessage(getResourceBundleString(PROVIDE_VALID_EMAIL));
      setActivatePvtMsg(activate);
      return MESSAGE_SETTING_PG;
    }
    else
    {
      Area area = prtMsgManager.getPrivateMessageArea();

      Boolean formAreaEnabledValue = (SET_AS_YES.equals(activate)) ? Boolean.TRUE : Boolean.FALSE;
      area.setEnabled(formAreaEnabledValue);

      try {
          int formSendToEmail = Integer.parseInt(sendToEmail);
          area.setSendToEmail(formSendToEmail);
      } catch (NumberFormatException nfe) {
          // if this happens, there is likely something wrong in the UI that needs to be fixed
          LOG.warn("Non-numeric option for sending email to recipient email address on Message screen. This may indicate a UI problem.");
          setErrorMessage(getResourceBundleString("pvt_send_to_email_invalid"));
          return MESSAGE_SETTING_PG;
      }

      Boolean formAutoForward = (SET_AS_YES.equals(forward)) ? Boolean.TRUE : Boolean.FALSE;
      forum.setAutoForward(formAutoForward);
      if (Boolean.TRUE.equals(formAutoForward)){
        forum.setAutoForwardEmail(email);
      }
      else{
        forum.setAutoForwardEmail(null);
      }

      area.setHiddenGroups(new HashSet(hiddenGroups));

      prtMsgManager.saveAreaAndForumSettings(area, forum);

      if (isMessagesandForums()) {
    	  return MAIN_PG;
      }
      else {
    	  return MESSAGE_HOME_PG;
      }
    }

  }

  ///////////////////   FOLDER SETTINGS         ///////////////////////
  private String addFolder;
  private boolean ismutable;
  private int totalMsgInFolder;
  public String getAddFolder()
  {
    return addFolder ;
  }
  public void setAddFolder(String addFolder)
  {
    this.addFolder=addFolder;
  }

  public boolean getIsmutable()
  {
    return prtMsgManager.isMutableTopicFolder(getSelectedTopicId());
  }

  public int getTotalMsgInFolder()
  {
    return totalMsgInFolder;
  }

  public void setTotalMsgInFolder(int totalMsgInFolder)
  {
    this.totalMsgInFolder = totalMsgInFolder;
  }

  //navigated from header pagecome from Header page
  public String processPvtMsgFolderSettings() {
    LOG.debug("processPvtMsgFolderSettings()");
    //String topicTitle= getExternalParameterByKey("pvtMsgTopicTitle");
    String topicTitle = forumManager.getTopicByUuid(getExternalParameterByKey("pvtMsgTopicId")).getTitle();
    setSelectedTopicTitle(topicTitle) ;
    String topicId=getExternalParameterByKey("pvtMsgTopicId") ;
    setSelectedTopicId(topicId);

    setFromMainOrHp();

    return MESSAGE_FOLDER_SETTING_PG;
  }

  public String processPvtMsgFolderSettingRevise() {
    LOG.debug("processPvtMsgFolderSettingRevise()");

    if(this.ismutable)
    {
      return null;
    }else
    {
      selectedNewTopicTitle = selectedTopicTitle;
      return REVISE_FOLDER_PG ;
    }
  }

  public String processPvtMsgFolderSettingAdd() {
    LOG.debug("processPvtMsgFolderSettingAdd()");

    setFromMainOrHp();
    this.setAddFolder("");  // make sure the input box is empty

    return ADD_MESSAGE_FOLDER_PG ;
  }
  public String processPvtMsgFolderSettingDelete() {
    LOG.debug("processPvtMsgFolderSettingDelete()");

    setFromMainOrHp();

    String typeUuid = getPrivateMessageTypeFromContext(selectedTopicTitle);

    setTotalMsgInFolder(prtMsgManager.findMessageCount(typeUuid, aggregateList));

    if(ismutable)
    {
      setErrorMessage(getResourceBundleString(CANNOT_DEL_REVISE_FOLDER));
      return null;
    }else {
      setErrorMessage(getResourceBundleString(CONFIRM_FOLDER_DELETE));
      return DELETE_FOLDER_PG;
    }
  }

  public String processPvtMsgReturnToMainOrHp()
  {
	  LOG.debug("processPvtMsgReturnToMainOrHp()");
	    if(fromMainOrHp != null && (fromMainOrHp.equals(MESSAGE_HOME_PG) || (fromMainOrHp.equals(MAIN_PG))))
	    {
	    	String returnToPage = fromMainOrHp;
			fromMainOrHp = "";
			return returnToPage;
	    }
	    else
	    {
	    	return MAIN_PG ;
	    }
  }

  public String processPvtMsgReturnToFolderView()
  {
	  return MESSAGE_FOLDER_SETTING_PG;
  }

  //Create a folder within a forum
  public String processPvtMsgFldCreate()
  {
    LOG.debug("processPvtMsgFldCreate()");

    String createFolder=getAddFolder() ;
    StringBuilder alertMsg = new StringBuilder();
    createFolder = FormattedText.processFormattedText(createFolder, alertMsg);
    if(createFolder == null || createFolder.trim().length() == 0)
    {
    	setErrorMessage(getResourceBundleString(ENTER_FOLDER_NAME));
      	return null ;
    } else if((PVTMSG_MODE_RECEIVED.toLowerCase()).equals(createFolder.toLowerCase().trim()) || (PVTMSG_MODE_SENT.toLowerCase()).equals(createFolder.toLowerCase().trim())||
    		 (PVTMSG_MODE_DELETE.toLowerCase()).equals(createFolder.toLowerCase().trim()) || (PVTMSG_MODE_DRAFT.toLowerCase()).equals(createFolder.toLowerCase().trim()))
    {
    	setErrorMessage(getResourceBundleString(CREATE_DIFF_FOLDER_NAME));
    	return null;
    } else if(createFolder.length() > 100)
    {
    	setErrorMessage(getResourceBundleString(ENTER_SHORTER_NAME));
    	return null;
    } else
    {
        prtMsgManager.createTopicFolderInForum(forum, createFolder);
      //create a typeUUID in commons
       String newTypeUuid= typeManager.getCustomTopicType(createFolder);
    }
      //since PrivateMessagesTool has a session scope,
      //reset addFolder to blank for new form
      addFolder = "";
      return processPvtMsgReturnToMainOrHp();
   }

  private String selectedNewTopicTitle=selectedTopicTitle;  //default
  public String getSelectedNewTopicTitle()
  {
    return selectedNewTopicTitle;
  }
  public void setSelectedNewTopicTitle(String selectedNewTopicTitle)
  {
    this.selectedNewTopicTitle = selectedNewTopicTitle;
  }

  /**
   * revise
   **/
  public String processPvtMsgFldRevise()
  {
    LOG.debug("processPvtMsgFldRevise()");

    String newTopicTitle = this.getSelectedNewTopicTitle();

    if(!hasValue(newTopicTitle))
    {
      setErrorMessage(getResourceBundleString(FOLDER_NAME_BLANK));
      return REVISE_FOLDER_PG;
    }
    else if((PVTMSG_MODE_RECEIVED.toLowerCase()).equals(newTopicTitle.toLowerCase().trim()) || (PVTMSG_MODE_SENT.toLowerCase()).equals(newTopicTitle.toLowerCase().trim())||
   		 (PVTMSG_MODE_DELETE.toLowerCase()).equals(newTopicTitle.toLowerCase().trim()) || (PVTMSG_MODE_DRAFT.toLowerCase()).equals(newTopicTitle.toLowerCase().trim()))
    {
   	  setErrorMessage(getResourceBundleString(CREATE_DIFF_FOLDER_NAME));
   	  return REVISE_FOLDER_PG;
    }
    else if(newTopicTitle.length() > 100)
    {
   	  setErrorMessage(getResourceBundleString(ENTER_SHORTER_NAME));
   	  return REVISE_FOLDER_PG;
    }
    else {
      List tmpMsgList = prtMsgManager.getMessagesByType(typeManager.getCustomTopicType(prtMsgManager.getTopicByUuid(selectedTopicId).getTitle()), PrivateMessageManager.SORT_COLUMN_DATE,
          PrivateMessageManager.SORT_ASC);
      prtMsgManager.renameTopicFolder(forum, selectedTopicId,  newTopicTitle);
      //rename topic in commons -- as messages are linked through commons type
      //TODO - what if more than one type objects are returned-- We need to switch from title
      String newTypeUuid = typeManager.renameCustomTopicType(selectedTopicTitle, newTopicTitle);
      for(int i=0; i<tmpMsgList.size(); i++)
      {
      	PrivateMessage tmpPM = (PrivateMessage) tmpMsgList.get(i);
      	List tmpRecipList = tmpPM.getRecipients();
      	tmpPM.setTypeUuid(newTypeUuid);
      	String currentUserId = SessionManager.getCurrentSessionUserId();
      	Iterator iter = tmpRecipList.iterator();
      	while(iter.hasNext())
      	{
      		PrivateMessageRecipient tmpPMR = (PrivateMessageRecipient) iter.next();
      		if(tmpPMR != null && tmpPMR.getUserId().equals(currentUserId))
      		{
      			tmpPMR.setTypeUuid(newTypeUuid);
      		}
      	}
      	tmpPM.setRecipients(tmpRecipList);
      	prtMsgManager.savePrivateMessage(tmpPM, false);
      }
    }
    setSelectedTopicTitle(newTopicTitle) ;
    return MESSAGE_FOLDER_SETTING_PG ;
  }

  //Delete
  public String processPvtMsgFldDelete()
  {
    LOG.debug("processPvtMsgFldDelete()");

    prtMsgManager.deleteTopicFolder(forum,getSelectedTopicId()) ;

    //delete the messages
    String typeUuid = getPrivateMessageTypeFromContext(selectedTopicTitle);
    List allPvtMsgs= prtMsgManager.getMessagesByType(typeUuid,PrivateMessageManager.SORT_COLUMN_DATE,
        PrivateMessageManager.SORT_DESC);
    for (Iterator iter = allPvtMsgs.iterator(); iter.hasNext();)
    {
      PrivateMessage element = (PrivateMessage) iter.next();
      prtMsgManager.deletePrivateMessage(element, typeUuid);
    }
    return processPvtMsgReturnToMainOrHp();
  }

  //create folder within folder
  public String processPvtMsgFolderInFolderAdd()
  {
    LOG.debug("processPvtMsgFolderSettingAdd()");

    setFromMainOrHp();
    this.setAddFolder("");

    return ADD_FOLDER_IN_FOLDER_PG ;
  }

  //create folder within Folder
  //TODO - add parent fodler id for this
  public String processPvtMsgFldInFldCreate()
  {
    LOG.debug("processPvtMsgFldCreate()");

    PrivateTopic parentTopic=(PrivateTopic) prtMsgManager.getTopicByUuid(selectedTopicId);

    String createFolder=getAddFolder() ;
    if(createFolder == null || createFolder.trim().length() == 0)
    {
      setErrorMessage(getResourceBundleString(ENTER_FOLDER_NAME));
      return null ;
    }
    else if((PVTMSG_MODE_RECEIVED.toLowerCase()).equals(createFolder.toLowerCase().trim()) || (PVTMSG_MODE_SENT.toLowerCase()).equals(createFolder.toLowerCase().trim())||
   		 (PVTMSG_MODE_DELETE.toLowerCase()).equals(createFolder.toLowerCase().trim()) || (PVTMSG_MODE_DRAFT.toLowerCase()).equals(createFolder.toLowerCase().trim()))
    {
      setErrorMessage(getResourceBundleString(CREATE_DIFF_FOLDER_NAME));
   	  return null;
    }
    else if(createFolder.length() > 100)
    {
   	  setErrorMessage(getResourceBundleString(ENTER_SHORTER_NAME));
   	  return null;
    }
    else
    {
        prtMsgManager.createTopicFolderInTopic(forum, parentTopic, createFolder);
      //create a typeUUID in commons
      String newTypeUuid= typeManager.getCustomTopicType(createFolder);
    }

      addFolder = "";
      return processPvtMsgReturnToMainOrHp();

  }
  ///////////////////// MOVE    //////////////////////
  private String moveToTopic="";
  private String moveToNewTopic="";

  public String getMoveToTopic()
  {
    if(hasValue(moveToNewTopic))
    {
      moveToTopic=moveToNewTopic;
    }
    return moveToTopic;
  }
  public void setMoveToTopic(String moveToTopic)
  {
    this.moveToTopic = moveToTopic;
  }

  /**
   * called from Single delete Page
   * @return - pvtMsgMove
   */
  public String processPvtMsgMove() {
    LOG.debug("processPvtMsgMove()");
    return MOVE_MESSAGE_PG;
  }

  public void processPvtMsgParentFolderMove(ValueChangeEvent event)
  {
    LOG.debug("processPvtMsgSettingsRevise()");
    if ((String)event.getNewValue() != null)
    {
      moveToNewTopic= (String)event.getNewValue();
    }
  }

  public String processPvtMsgMoveMessage()
  {
    LOG.debug("processPvtMsgMoveMessage()");
    String moveTopicTitle=getMoveToTopic(); //this is uuid of new topic
    if( moveTopicTitle == null || moveTopicTitle.trim().length() == 0){
    	setErrorMessage(getResourceBundleString(MOVE_MSG_ERROR));
    	return null;
    }

    Topic newTopic= prtMsgManager.getTopicByUuid(moveTopicTitle);
    Topic oldTopic=selectedTopic.getTopic();
    if (newTopic.getUuid().equals(oldTopic.getUuid())) {
    	//error
    	setErrorMessage(getResourceBundleString(MOVE_MSG_ERROR));
    	return null;
    }
    else{
    	if (selectedMoveToFolderItems == null)
    	{
    		prtMsgManager.movePvtMsgTopic(detailMsg.getMsg(), oldTopic, newTopic);
    	}
    	else
    	{
    		for (Iterator movingIter = selectedMoveToFolderItems.iterator(); movingIter.hasNext();)
    		{
    			PrivateMessageDecoratedBean decoMessage = (PrivateMessageDecoratedBean) movingIter.next();
		        final PrivateMessage initPrivateMessage = prtMsgManager.initMessageWithAttachmentsAndRecipients(decoMessage.getMsg());
    			decoMessage = new PrivateMessageDecoratedBean(initPrivateMessage);

    			prtMsgManager.movePvtMsgTopic(decoMessage.getMsg(), oldTopic, newTopic);
    		}
    	}

		//reset
		moveToTopic="";
		moveToNewTopic="";
		selectedMoveToFolderItems = null;

    	// Return to Messages & Forums page or Messages page
   		if (isMessagesandForums())
   		{
   			return MAIN_PG;
   		}
   		else
   		{
   			return MESSAGE_HOME_PG;
   		}
    }
  }

  /**
   *
   * @return
   */
  public String processPvtMsgCancelToDetailView()
  {
    LOG.debug("processPvtMsgCancelToDetailView()");
    this.deleteConfirm=false;

    // due to adding ability to move multiple messages
    if (selectedMoveToFolderItems != null)
    {
    	selectedMoveToFolderItems = null;
    	return DISPLAY_MESSAGES_PG;
    }

    return SELECTED_MESSAGE_PG;
  }

  ///////////////   SEARCH      ///////////////////////
  private List searchPvtMsgs;
  public List getSearchPvtMsgs()
  {
    if(selectView!=null && selectView.equalsIgnoreCase(THREADED_VIEW))
    {
        this.rearrageTopicMsgsThreaded(true);
    }
    //  If "check all", update the decorated pmb to show selected
    if (selectAll)
    {
    	Iterator searchIter = searchPvtMsgs.iterator();
    	while (searchIter.hasNext())
    	{
    		PrivateMessageDecoratedBean searchMsg = (PrivateMessageDecoratedBean)searchIter.next();
    		searchMsg.setIsSelected(true);
    	}

    	selectAll = false;
    }
    return searchPvtMsgs;
  }
  public void setSearchPvtMsgs(List searchPvtMsgs)
  {
    this.searchPvtMsgs=searchPvtMsgs ;
  }
  public String processSearch()
  {
    LOG.debug("processSearch()");
    multiDeleteSuccess = false;

    List newls = new ArrayList() ;
//    for (Iterator iter = getDecoratedPvtMsgs().iterator(); iter.hasNext();)
//    {
//      PrivateMessageDecoratedBean element = (PrivateMessageDecoratedBean) iter.next();
//
//      String message=element.getMsg().getTitle();
//      String searchText = getSearchText();
//      //if search on subject is set - default is true
//      if(searchOnSubject)
//      {
//        StringTokenizer st = new StringTokenizer(message);
//        while (st.hasMoreTokens())
//        {
//          if(st.nextToken().matches("(?i).*getSearchText().*")) //matches anywhere
//          //if(st.nextToken().equalsIgnoreCase(getSearchText()))
//          {
//            newls.add(element) ;
//            break;
//          }
//        }
//      }
//      //is search
//
//    }

    /**TODO -
     * In advance srearch as there can be ANY type of combination like selection of
     * ANY 1 or 2 or 3 or 4 or 5 options like - subject, Author By, label, body and date
     * so all possible cases are taken care off.
     * This doesn't look nice, but good this is that we are using same method - our backend is cleaner
     * First - checked if date is selected then purmutation of 4 options
     * ELSE - permutations of other 4 options
     */
    List tempPvtMsgLs= new ArrayList();

    if(searchOnDate && searchFromDate == null && searchToDate==null)
    {
       setErrorMessage(getResourceBundleString(MISSING_BEG_END_DATE));
    }

    if(!hasValue(searchText))
    {
       setErrorMessage(getResourceBundleString(ENTER_SEARCH_TEXT));
    }

    tempPvtMsgLs= prtMsgManager.searchPvtMsgs(getPrivateMessageTypeFromContext(msgNavMode),
          getSearchText(), getSearchFromDate(), getSearchToDate(),
          searchOnSubject, searchOnAuthor, searchOnBody, searchOnLabel, searchOnDate) ;

    newls= createDecoratedDisplay(tempPvtMsgLs);
//
//    for (Iterator iter = tempPvtMsgLs.iterator(); iter.hasNext();)
//    {
//      PrivateMessage element = (PrivateMessage) iter.next();
//      PrivateMessageDecoratedBean dbean = new PrivateMessageDecoratedBean(element);
//
//      //getRecipients() is filtered for this perticular user i.e. returned list of only one PrivateMessageRecipient object
//      for (Iterator iterator = element.getRecipients().iterator(); iterator.hasNext();)
//      {
//        PrivateMessageRecipient el = (PrivateMessageRecipient) iterator.next();
//        if (el != null){
//          if(!el.getRead().booleanValue())
//          {
//            dbean.setHasRead(el.getRead().booleanValue());
//            break;
//          }
//        }
//      }
//      //Add decorate 'TO' String for sent message
//      if(PVTMSG_MODE_SENT.equals(msgNavMode))
//      {
//        dbean.setSendToStringDecorated(createDecoratedSentToDisplay(dbean));
//      }
//      newls.add(dbean);
//    }
    //set threaded view as  false in search
    selectView="";

    if(newls.size()>0)
    {
      this.setSearchPvtMsgs(newls) ;
      return SEARCH_RESULT_MESSAGES_PG ;
    }
    else
      {
        setErrorMessage(getResourceBundleString(NO_MATCH_FOUND));
        return null;
      }
  }

  /**
   * Clear Search text
   */
  public String processClearSearch()
  {
    searchText="";
    if(searchPvtMsgs != null)
    {
      searchPvtMsgs.clear();
      //searchPvtMsgs= decoratedPvtMsgs;
    }

    searchOnBody=false ;
    searchOnSubject=true;
    searchOnLabel= false ;
    searchOnAuthor=false;
    searchOnDate=false;
    searchFromDate=null;
    searchToDate=null;

    return DISPLAY_MESSAGES_PG;
  }

  public boolean searchOnBody=false ;
  public boolean searchOnSubject=true;  //default is search on Subject
  public boolean searchOnLabel= false ;
  public boolean searchOnAuthor=false;
  public boolean searchOnDate=false;
  public Date searchFromDate;
  public Date searchToDate;

  public boolean isSearchOnAuthor()
  {
    return searchOnAuthor;
  }
  public void setSearchOnAuthor(boolean searchOnAuthor)
  {
    this.searchOnAuthor = searchOnAuthor;
  }
  public boolean isSearchOnBody()
  {
    return searchOnBody;
  }
  public void setSearchOnBody(boolean searchOnBody)
  {
    this.searchOnBody = searchOnBody;
  }
  public boolean isSearchOnLabel()
  {
    return searchOnLabel;
  }
  public void setSearchOnLabel(boolean searchOnLabel)
  {
    this.searchOnLabel = searchOnLabel;
  }
  public boolean isSearchOnSubject()
  {
    return searchOnSubject;
  }
  public void setSearchOnSubject(boolean searchOnSubject)
  {
    this.searchOnSubject = searchOnSubject;
  }
  public boolean isSearchOnDate()
  {
    return searchOnDate;
  }
  public void setSearchOnDate(boolean searchOnDate)
  {
    this.searchOnDate = searchOnDate;
  }
  public Date getSearchFromDate()
  {
    return searchFromDate;
  }
  public void setSearchFromDate(Date searchFromDate)
  {
    this.searchFromDate = searchFromDate;
  }
  public Date getSearchToDate()
  {
    return searchToDate;
  }
  public void setSearchToDate(Date searchToDate)
  {
    this.searchToDate = searchToDate;
  }

  //////////////        HELPER      //////////////////////////////////
  /**
   * @return
   */
  private String getExternalParameterByKey(String parameterId)
  {
    ExternalContext context = FacesContext.getCurrentInstance()
        .getExternalContext();
    Map paramMap = context.getRequestParameterMap();

    return (String) paramMap.get(parameterId);
  }

  /**
   * decorated display - from List of Message
   */
  public List createDecoratedDisplay(List msg)
  {
    List decLs= new ArrayList() ;
    numberChecked = 0;

    for (Iterator iter = msg.iterator(); iter.hasNext();)
    {
      PrivateMessage element = (PrivateMessage) iter.next();

      PrivateMessageDecoratedBean dbean= new PrivateMessageDecoratedBean(element);
      //if processSelectAll is set, then set isSelected true for all messages,
      if(selectAll)
      {
        dbean.setIsSelected(true);
        numberChecked++;
      }

      //getRecipients() is filtered for this particular user i.e. returned list of only one PrivateMessageRecipient object
      for (Iterator iterator = element.getRecipients().iterator(); iterator.hasNext();)
      {
        PrivateMessageRecipient el = (PrivateMessageRecipient) iterator.next();
        if (el != null){
          dbean.setHasRead(el.getRead().booleanValue());
          dbean.setReplied(el.getReplied().booleanValue());
        }
      }
      //Add decorate 'TO' String for sent message
      if(PVTMSG_MODE_SENT.equals(msgNavMode))
      {
        dbean.setSendToStringDecorated(createDecoratedSentToDisplay(dbean));
      }

      decLs.add(dbean) ;
    }
    //reset selectAll flag, for future use
    selectAll=false;
    return decLs;
  }

  /**
   * create decorated display for Sent To display for Sent folder
   * @param dbean
   * @return
   */
  public String createDecoratedSentToDisplay(PrivateMessageDecoratedBean dbean)
  {
    String deocratedToDisplay="";
    if(dbean.getMsg().getRecipientsAsText() != null)
    {
      if (dbean.getMsg().getRecipientsAsText().length()>25)
      {
        deocratedToDisplay=(dbean.getMsg().getRecipientsAsText()).substring(0, 20)+" (..)";
      } else
      {
        deocratedToDisplay=dbean.getMsg().getRecipientsAsText();
      }
    }
    return deocratedToDisplay;
  }

  /**
   * get recipients
   * @return a set of recipients (User objects)
   */
  private Map<User, Boolean> getRecipients()
  {
	  Map<User, Boolean> returnSet = new HashMap<User, Boolean>();

    /** get List of unfiltered course members */
    List allCourseUsers = membershipManager.getAllCourseUsers();

    Map<User, Boolean> composeToSet = getRecipientsHelper(getSelectedComposeToList(), allCourseUsers, false);
    Map<User, Boolean> composeBccSet = getRecipientsHelper(getSelectedComposeBccList(), allCourseUsers, true);

    //first add the BCC list, then remove the duplicates, then add the regular To list
    //Do this to make the regular TO list have precident over the BCC list.  This is done
    //because of the recipientsAsText list that is created.  When replying, it would cause
    //names to show up that are BCC'ed, and who don't actually get replies
    returnSet.putAll(composeBccSet);
    //remove all duplicates by doing this first:
    for (Iterator iterator = composeToSet.keySet().iterator(); iterator.hasNext();) {
    	User user = (User) iterator.next();
    	if(returnSet.containsKey(user)){
    		returnSet.remove(user);
    	}
    }
    //now add them all back
    returnSet.putAll(composeToSet);

    return returnSet;
  }
  //=========HUXT BEGIN

  private Map<User, Boolean> getRecipientsHelper(List selectedList, List allCourseUsers, boolean bcc){

	  Map<User, Boolean>  returnSet = new HashMap<User, Boolean>();

	  for (Iterator i = selectedList.iterator(); i.hasNext();){
		  String selectedItem = (String) i.next();

		  /** lookup item in map */
		  MembershipItem item = (MembershipItem) courseMemberMap.get(selectedItem);
		  if (item == null){
			  LOG.warn("getRecipients() could not resolve uuid: " + selectedItem);
		  }
		  else{
			  if (MembershipItem.TYPE_ALL_PARTICIPANTS.equals(item.getType())){
				  for (Iterator a = allCourseUsers.iterator(); a.hasNext();){
					  MembershipItem member = (MembershipItem) a.next();
					  returnSet.put(member.getUser(), bcc);
				  }
				  //if all users have been selected we may as well return and ignore any other entries
				  return returnSet;
			  }
			  else if (MembershipItem.TYPE_ROLE.equals(item.getType())){
				  for (Iterator r = allCourseUsers.iterator(); r.hasNext();){
					  MembershipItem member = (MembershipItem) r.next();
					  if (member.getRole().equals(item.getRole())){
						  returnSet.put(member.getUser(), bcc);
					  }
				  }
			  }
			  else if (MembershipItem.TYPE_GROUP.equals(item.getType())){
				  for (Iterator g = allCourseUsers.iterator(); g.hasNext();){
					  MembershipItem member = (MembershipItem) g.next();
					  Set groupMemberSet = item.getGroup().getMembers();
					  for (Iterator s = groupMemberSet.iterator(); s.hasNext();){
						  Member m = (Member) s.next();
						  if (m.getUserId() != null && m.getUserId().equals(member.getUser().getId())){
							  returnSet.put(member.getUser(), bcc);
						  }
					  }
				  }
			  }
			  else if (MembershipItem.TYPE_USER.equals(item.getType())){
				  returnSet.put(item.getUser(), bcc);
			  }
			  else{
				  LOG.warn("getRecipients() could not resolve membership type: " + item.getType());
			  }
		  }
	  }
	  return returnSet;
  }

  //=========huxt ENG
  /**
   * getUserRecipients
   * @param courseMembers
   * @return set of all User objects for course
   */
  private Set getUserRecipients(Set courseMembers){
    Set returnSet = new HashSet();

    for (Iterator i = courseMembers.iterator(); i.hasNext();){
      MembershipItem item = (MembershipItem) i.next();
        returnSet.add(item.getUser());
    }
    return returnSet;
  }

  /**
   * getUserRecipientsForRole
   * @param roleName
   * @param courseMembers
   * @return set of all User objects for role
   */
  private Set getUserRecipientsForRole(String roleName, Set courseMembers){
    Set returnSet = new HashSet();

    for (Iterator i = courseMembers.iterator(); i.hasNext();){
      MembershipItem item = (MembershipItem) i.next();
      if (item.getRole().getId().equalsIgnoreCase(roleName)){
        returnSet.add(item.getUser());
      }
    }
    return returnSet;
  }

  private String getPrivateMessageTypeFromContext(String navMode){
    if(PVTMSG_MODE_RECEIVED.equals(navMode))
        return typeManager.getReceivedPrivateMessageType();
   	else if(PVTMSG_MODE_SENT.equals(navMode))
        return typeManager.getSentPrivateMessageType();
   	else if(PVTMSG_MODE_DELETE.equals(navMode))
        return typeManager.getDeletedPrivateMessageType();
   	else if (PVTMSG_MODE_DRAFT.equalsIgnoreCase(navMode))
   		return typeManager.getDraftPrivateMessageType();
   	else
   		return typeManager.getCustomTopicType(navMode);
  }

  //////// GETTER AND SETTER  ///////////////////
  public String processUpload(ValueChangeEvent event)
  {
    return DISPLAY_MESSAGES_PG ;
  }

  public String processUploadConfirm()
  {
    return DISPLAY_MESSAGES_PG;
  }

  public String processUploadCancel()
  {
    return DISPLAY_MESSAGES_PG ;
  }

  public void setForumManager(MessageForumsForumManager forumManager)
  {
    this.forumManager = forumManager;
  }

  public PrivateForum getForum()
  {
    return forum;
  }

  public void setForum(PrivateForum forum)
  {
    this.forum = forum;
  }

// public String processActionAreaSettingEmailFwd()
// {
//
// }

  /**
   * Check String has value, not null
   * @return boolean
   */
  protected boolean hasValue(String eval)
  {
    if (eval != null && !"".equals(eval.trim()))
    {
      return true;
    }
    else
    {
      return false;
    }
  }

  /**
   * @param errorMsg
   */
  private void setErrorMessage(String errorMsg)
  {
    LOG.debug("setErrorMessage(String " + errorMsg + ")");
    FacesContext.getCurrentInstance().addMessage(null,
        new FacesMessage(getResourceBundleString(ALERT) + ' ' + errorMsg));
  }

  private void setInformationMessage(String infoMsg)
  {
	    LOG.debug("setInformationMessage(String " + infoMsg + ")");
	    FacesContext.getCurrentInstance().addMessage(null,
	        new FacesMessage(infoMsg));
  }

  /**
   * Enable privacy message
   * @return
   */
  public boolean getRenderPrivacyAlert()
  {
   if(ServerConfigurationService.getString(MESSAGECENTER_PRIVACY_TEXT)!=null &&
       ServerConfigurationService.getString(MESSAGECENTER_PRIVACY_TEXT).trim().length()>0 )
   {
     return true;
   }
    return false;
  }

  /**
   * Get Privacy message link  from sakai.properties
   * @return
   */
  public String getPrivacyAlertUrl()
  {
    return ServerConfigurationService.getString(MESSAGECENTER_PRIVACY_URL);
  }

  /**
   * Get Privacy message from sakai.properties
   * @return
   */
  public String getPrivacyAlert()
  {
    return ServerConfigurationService.getString(MESSAGECENTER_PRIVACY_TEXT);
  }

  public boolean isAtMain(){
    HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();

    String servletPath = req.getServletPath();
    if (servletPath != null){
      if (servletPath.startsWith("/jsp/main")){
        return true;
      }
    }
    return false;
  }

	public String getSortType() {
		return sortType;
	}

	public void setSortType(String sortType) {
		this.sortType = sortType;
	}

    public static String getResourceBundleString(String key)
    {
        return rb.getString(key);
    }

    public static String getResourceBundleString(String key, Object[] args) {
    	return rb.getFormattedMessage(key, args);
    }

    public String getAuthorString()
    {
       String authorString = getUserId();

       try
       {
    	 User user = UserDirectoryService.getUser(getUserId());
    	 if (ServerConfigurationService.getBoolean("msg.displayEid", true))
    	 {
    		 authorString = user.getSortName() + " (" + user.getDisplayId() + ")";
    	 }
    	 else
    	 {
    		 authorString = user.getSortName();
    	 }
       }
       catch(Exception e)
       {
         e.printStackTrace();
       }

       return authorString;
    }

    public String getPlacementId()
    {
       return Validator.escapeJavascript("Main" + ToolManager.getCurrentPlacement().getId());
    }

    public boolean isSearchPvtMsgsEmpty()
    {
    	return searchPvtMsgs == null || searchPvtMsgs.isEmpty();
    }

    public void setMsgNavMode(String msgNavMode) {
		this.msgNavMode = msgNavMode;
	}

	/**
	 * @return
	 */
	public String processActionMarkCheckedAsRead()
	{
		return markCheckedMessages(true);
	}

	public String processActionMarkCheckedAsUnread() {
		return markCheckedMessages(false);
	}

	public String processActionDeleteChecked() {
	    LOG.debug("processActionDeleteChecked()");

		List pvtMsgList = getPvtMsgListToProcess();
		boolean msgSelected = false;
		selectedDeleteItems = new ArrayList();

		Iterator pvtMsgListIter = pvtMsgList.iterator();
		while (pvtMsgListIter.hasNext())
		{
			PrivateMessageDecoratedBean decoMessage = (PrivateMessageDecoratedBean) pvtMsgListIter.next();
			if(decoMessage.getIsSelected())
			{
				msgSelected = true;
				selectedDeleteItems.add(decoMessage);
			}
		}

		if (!msgSelected)
		{
			setErrorMessage(getResourceBundleString(NO_MARKED_DELETE_MESSAGE));
			return null;
		}

		return processPvtMsgMultiDelete();
	}

	public String processActionMoveCheckedToFolder() {
	    LOG.debug("processActionMoveCheckedToFolder()");

	    List pvtMsgList = getPvtMsgListToProcess();
	    boolean msgSelected = false;
	    selectedMoveToFolderItems = new ArrayList();

		Iterator pvtMsgListIter = pvtMsgList.iterator();
		while (pvtMsgListIter.hasNext())
		{
			PrivateMessageDecoratedBean decoMessage = (PrivateMessageDecoratedBean) pvtMsgListIter.next();
			if(decoMessage.getIsSelected())
			{
				msgSelected = true;
		        selectedMoveToFolderItems.add(decoMessage);
			}
		}

		if (!msgSelected)
		{
			setErrorMessage(getResourceBundleString(NO_MARKED_MOVE_MESSAGE));
			return null;
		}

	    moveToTopic = selectedTopicId;
	    return MOVE_MESSAGE_PG;

	}

	private List getPvtMsgListToProcess() {
		List pvtMsgList = new ArrayList();
		boolean searchMode = false;
		// determine if we are looking at search results or the main listing
		if (searchPvtMsgs != null && !searchPvtMsgs.isEmpty())
		{
			searchMode = true;
			pvtMsgList = searchPvtMsgs;
		}
		else
		{
			pvtMsgList = decoratedPvtMsgs;
		}

		return pvtMsgList;
	}
	/**
	 *
	 * @param readStatus
	 * @return
	 */
	private String markCheckedMessages(boolean readStatus)
	{
		List pvtMsgList = getPvtMsgListToProcess();
		boolean msgSelected = false;
		boolean searchMode = false;

		Iterator pvtMsgListIter = pvtMsgList.iterator();
		while (pvtMsgListIter.hasNext())
		{
			PrivateMessageDecoratedBean decoMessage = (PrivateMessageDecoratedBean) pvtMsgListIter.next();
			if(decoMessage.getIsSelected())
			{
				msgSelected = true;
				if (readStatus) {
					prtMsgManager.markMessageAsReadForUser(decoMessage.getMsg());
				} else {
					prtMsgManager.markMessageAsUnreadForUser(decoMessage.getMsg());
				}

				if (searchMode)
				{
					// Although the change was made in the db, the search
					// view needs to be refreshed (it doesn't return to db)
					decoMessage.setHasRead(true);
					decoMessage.setIsSelected(false);
				}
			}
		}

		if (!msgSelected)
		{
			setErrorMessage(getResourceBundleString(NO_MARKED_READ_MESSAGE));
			return null;
		}

		if (searchMode)
		{
			return SEARCH_RESULT_MESSAGES_PG;
		}

		return DISPLAY_MESSAGES_PG;
	}

	private void setFromMainOrHp()
	{
		String fromPage = getExternalParameterByKey(COMPOSE_FROM_PG);
	    if(fromPage != null && (fromPage.equals(MESSAGE_HOME_PG) || (fromPage.equals(MAIN_PG))))
	    {
	    	fromMainOrHp = fromPage;
	    }
	}

	@SuppressWarnings("unchecked")
	public String processActionPermissions()
	{
		ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
		ToolSession toolSession = SessionManager.getCurrentToolSession();

		try {
			String url = "../sakai.permissions.helper.helper/tool?" +
			"session." + PermissionsHelper.DESCRIPTION + "=" +
			org.sakaiproject.util.Web.escapeUrl(getResourceBundleString("pvt_properties_desc")) +
			"&session." + PermissionsHelper.TARGET_REF + "=" +
			SiteService.getSite(ToolManager.getCurrentPlacement().getContext()).getReference() +
			"&session." + PermissionsHelper.PREFIX + "=" +
			DefaultPermissionsManager.MESSAGE_FUNCTION_PREFIX + DefaultPermissionsManager.MESSAGE_FUNCITON_PREFIX_PERMISSIONS;

			// Set permission descriptions
			if (toolSession != null) {
				ResourceLoader pRb = new ResourceLoader(PERMISSIONS_BUNDLE);
				HashMap<String, String> pRbValues = new HashMap<String, String>();
				for (Iterator<Entry<String, String>> iEntries = pRb.entrySet().iterator();iEntries.hasNext();)
				{
					Entry<String, String> entry = iEntries.next();
					String key = entry.getKey();
					pRbValues.put(key, entry.getValue());
				}

				toolSession.setAttribute("permissionDescriptions", pRbValues);

				// set group awareness
				 String groupAware = ToolManager.getCurrentTool().getRegisteredConfig().getProperty("groupAware");
				 toolSession.setAttribute("groupAware", groupAware != null ? Boolean.valueOf(groupAware) : Boolean.FALSE);
			}

			// Invoke Permissions helper
			context.redirect(url);
		}
		catch (IOException e) {
			throw new RuntimeException("Failed to redirect to helper", e);
		}catch (IdUnusedException e){
			throw new RuntimeException("Failed to redirect to helper", e);
		}
		return null;
	}

	/**
	 * @return TRUE if within Messages & Forums tool, FALSE otherwise
	 */
	public boolean isMessagesandForums() {
		return messageManager.currentToolMatch(MESSAGECENTER_TOOL_ID);
	}

	/**
	 * @return TRUE if within Messages tool, FALSE otherwise
	 */
	public boolean isMessages() {
		return messageManager.currentToolMatch(MESSAGES_TOOL_ID);
	}

	/**
	 * @return TRUE if Message Forums (Message Center) exists in this site,
	 *         FALSE otherwise
	 */
	public boolean isMessageForumsPageInSite() {
		return isMessageForumsPageInSite(getSiteId());
	}

	/**
	 * @return TRUE if Messages & Forums (Message Center) exists in this site,
	 *         FALSE otherwise
	 */
	private boolean isMessageForumsPageInSite(String siteId) {
		return messageManager.isToolInSite(siteId, MESSAGECENTER_TOOL_ID);
	}

	/**
	 * @return TRUE if Messages tool exists in this site,
	 *         FALSE otherwise
	 */
	public boolean isMessagesPageInSite() {
		return isMessagesPageInSite(getSiteId());
	}

	/**
	 * @return TRUE if Messages tool exists in this site,
	 *         FALSE otherwise
	 */
	private boolean isMessagesPageInSite(String siteId) {
		return messageManager.isToolInSite(siteId, MESSAGES_TOOL_ID);
	}

	private String getEventMessage(Object object) {
	  	String eventMessagePrefix = "";
	  	final String toolId = ToolManager.getCurrentTool().getId();

		if (toolId.equals(DiscussionForumService.MESSAGE_CENTER_ID))
			eventMessagePrefix = "/messages&Forums/site/";
		else if (toolId.equals(DiscussionForumService.MESSAGES_TOOL_ID))
			eventMessagePrefix = "/messages/site/";
		else
			eventMessagePrefix = "/forums/site/";

	  	return eventMessagePrefix + ToolManager.getCurrentPlacement().getContext() +
	  				"/" + object.toString() + "/" + SessionManager.getCurrentSessionUserId();
	}

	public void setContentHostingService(ContentHostingService contentHostingService) {
		this.contentHostingService = contentHostingService;
	}

	public SynopticMsgcntrManager getSynopticMsgcntrManager() {
		return synopticMsgcntrManager;
	}

	public void setSynopticMsgcntrManager(
			SynopticMsgcntrManager synopticMsgcntrManager) {
		this.synopticMsgcntrManager = synopticMsgcntrManager;
	}

	public void setUserPreferencesManager(UserPreferencesManager userPreferencesManager) {
		this.userPreferencesManager = userPreferencesManager;
	}

	public String getMobileSession()
	{
		Session session = SessionManager.getCurrentSession();
		String rv = session.getAttribute("is_wireless_device") != null && ((Boolean) session.getAttribute("is_wireless_device")).booleanValue()?"true":"false";
		return rv;
	}

	public boolean getCurrentSiteHasGroups(){
		Site currentSite = getCurrentSite();
		if(currentSite != null){
			return currentSite.hasGroups();
		}else{
			return false;
		}
	}

	public Site getCurrentSite(){
		try{
			return SiteService.getSite(ToolManager.getCurrentPlacement().getContext());
		} catch (IdUnusedException e) {
			LOG.error(e);
		}
		return null;
	}

	public List<SelectItem> getNonHiddenGroups(){
		nonHiddenGroups = new ArrayList<SelectItem>();
		nonHiddenGroups.add(new SelectItem(DEFAULT_NON_HIDDEN_GROUP_ID, getResourceBundleString(DEFAULT_NON_HIDDEN_GROUP_TITLE)));

		Site currentSite = getCurrentSite();
		if(currentSite.hasGroups()){

			Collection groups = currentSite.getGroups();

			groups = sortGroups(groups);

			for (Iterator groupIterator = groups.iterator(); groupIterator.hasNext();)
			{
				Group currentGroup = (Group) groupIterator.next();
				if(!isGroupHidden(currentGroup.getTitle())){
					nonHiddenGroups.add(new SelectItem(currentGroup.getTitle(), currentGroup.getTitle()));
				}
			}
		}

		return nonHiddenGroups;
	}

	private boolean isGroupHidden(String groupName){
		for (HiddenGroup hiddenGroup : getHiddenGroups()) {
			if(hiddenGroup.getGroupId().equals(groupName)){
				return true;
			}
		}
		return false;
	}

	public List<HiddenGroup> getHiddenGroups(){
		return hiddenGroups;
	}

	public void setHiddenGroups(List<HiddenGroup> hiddenGroups){
		this.hiddenGroups = hiddenGroups;
	}

	/**
	   * Takes groups defined and sorts them alphabetically by title
	   * so will be in some order when displayed on permission widget.
	   *
	   * @param groups
	   * 			Collection of groups to be sorted
	   *
	   * @return
	   * 		Collection of groups in sorted order
	   */
	  private Collection sortGroups(Collection groups) {
		  List sortGroupsList = new ArrayList();

		  sortGroupsList.addAll(groups);

		  final GroupComparator groupComparator = new GroupComparator("title", true);

		  Collections.sort(sortGroupsList, groupComparator);

		  groups.clear();

		  groups.addAll(sortGroupsList);

		  return groups;
	  }

	  public String getSelectedNonHiddenGroup(){
		  return selectedNonHiddenGroup;
	  }

	  public void setSelectedNonHiddenGroup(String selectedNonHiddenGroup){
		  this.selectedNonHiddenGroup = selectedNonHiddenGroup;
	  }

	  public void processActionAddHiddenGroup(ValueChangeEvent event){
		  String selectedGroup = (String) event.getNewValue();
		  if(!DEFAULT_NON_HIDDEN_GROUP_ID.equals(selectedGroup) && !isGroupHidden(selectedGroup)){
			  getHiddenGroups().add(new HiddenGroupImpl(selectedGroup));
			  selectedNonHiddenGroup = DEFAULT_NON_HIDDEN_GROUP_ID;
		  }
	  }

	  public String processActionRemoveHiddenGroup(){
		  String groupId = getExternalParameterByKey(PARAM_GROUP_ID);
		  if(groupId != null && !"".equals(PARAM_GROUP_ID)){
			  for (HiddenGroup hiddenGroup : getHiddenGroups()) {
				  if(hiddenGroup.getGroupId().equals(groupId)){
					  getHiddenGroups().remove(hiddenGroup);
					  break;
				  }
			  }
		  }

		  return null;
	  }
		public Locale getUserLocale(){
			return new ResourceLoader().getLocale();
		}

    private LRS_Statement getStatementForUserReadPvtMsg(LRS_Actor student, String subject) {
        String url = ServerConfigurationService.getPortalUrl();
        LRS_Verb verb = new LRS_Verb(SAKAI_VERB.interacted);
        LRS_Object lrsObject = new LRS_Object(url + "/privateMessage", "read-private-message");
        HashMap<String, String> nameMap = new HashMap<String, String>();
        nameMap.put("en-US", "User read a private message");
        lrsObject.setActivityName(nameMap);
        HashMap<String, String> descMap = new HashMap<String, String>();
        descMap.put("en-US", "User read a private message with subject: " + subject);
        lrsObject.setDescription(descMap);
        return new LRS_Statement(student, verb, lrsObject);
    }

    private LRS_Statement getStatementForUserSentPvtMsg(LRS_Actor student, String subject, SAKAI_VERB sakaiVerb) {
        String url = ServerConfigurationService.getPortalUrl();
        LRS_Verb verb = new LRS_Verb(sakaiVerb);
        LRS_Object lrsObject = new LRS_Object(url + "/privateMessage", "send-private-message");
        HashMap<String, String> nameMap = new HashMap<String, String>();
        nameMap.put("en-US", "User sent a private message");
        lrsObject.setActivityName(nameMap);
        HashMap<String, String> descMap = new HashMap<String, String>();
        descMap.put("en-US", "User sent a private message with subject: " + subject);
        lrsObject.setDescription(descMap);
        return new LRS_Statement(student, verb, lrsObject);
    }
}

redpajama_set_name: RedPajamaGithub