Package org.olat.instantMessaging.groupchat

Source Code of org.olat.instantMessaging.groupchat.InstantMessagingGroupChatController

/**
* OLAT - Online Learning and Training<br />
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br />
* you may not use this file except in compliance with the License.<br />
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br />
* software distributed under the License is distributed on an "AS IS" BASIS,
* <br />
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br />
* See the License for the specific language governing permissions and <br />
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br />
* University of Zurich, Switzerland.
* <p>
*/
package org.olat.instantMessaging.groupchat;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.olat.basesecurity.ManagerFactory;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.commons.taskExecutor.TaskExecutorManager;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.htmlheader.jscss.JSAndCSSComponent;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.link.LinkFactory;
import org.olat.core.gui.components.panel.Panel;
import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.gui.control.floatingresizabledialog.FloatingResizableDialogController;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.UserConstants;
import org.olat.core.logging.AssertException;
import org.olat.core.util.event.GenericEventListener;
import org.olat.instantMessaging.ClientHelper;
import org.olat.instantMessaging.InstantMessagingEvent;
import org.olat.instantMessaging.InstantMessagingModule;

/**
* Description:<br />
* Handles an group chat in an floating window with all events like receiving messages, sending messages and updating an roster with all joined users
*
* There are several options how to display or start the chat as it gets used in different places
* Initial Date: 13.03.2007 <br />
*
* @author guido
*/
public class InstantMessagingGroupChatController extends BasicController implements GenericEventListener {
 
  private static final String NICKNAME_PREFIX = "anonym_";
  private String NICKNAME_ANONYMOUS;
  private XMPPConnection connection;
  private MultiUserChat muc;
  private VelocityContainer errorCompact = createVelocityContainer("errorCompact");
  private VelocityContainer error = createVelocityContainer("error");
  private VelocityContainer groupchatVC = createVelocityContainer("groupchat");
  private VelocityContainer groupChatMsgFieldVC = createVelocityContainer("groupChatMsgField");
  private VelocityContainer summaryCompactVC = createVelocityContainer("summaryCompact");
  private VelocityContainer rosterVC = createVelocityContainer("roster");
  private VelocityContainer summaryVC = createVelocityContainer("summary");
  private Panel groupChatMsgPanel;
  private Integer occupantsCount = 1;
  private ToggleAnonymousForm toggleAnonymousForm;
  private SendMessageForm sendMessageForm;
  private String roomJID;
  private StringBuilder messageHistory;
  private Link openGroupChatPanel;
  private Link indicateNewMessage;
  private Link openGroupChatPanelButton;
  private Link refresh;
  private Panel main, roster;
  private GroupChatJoinTask roomJoinTask;
  private boolean chatWindowOpen = false;
  private Locale locale;
  private Controller floatingResizablePanelCtr;
  private OLATResourceable ores;
  private final Panel chatWindowHolder;
  private final boolean compact;
  private String roomName;
  private long latestRosterUpdate = 0;
  private JSAndCSSComponent jsc;
  private List<String> rosterList = new ArrayList<String>();
  private boolean anonymousInChatroom;
  private boolean lazyCreation;
  private boolean initDone;
 
  /**
   *
   * @param ureq
   * @param wControl
   * @param ores
   * @param roomName
   * @param fixcsspanel if you want the panel rendered somewhere else to solve css issues add it here otherwise null
   * @param lazyCreation if true the user does not get joined automatically to the chatRoom
   */
  public InstantMessagingGroupChatController(UserRequest ureq, WindowControl wControl, OLATResourceable ores, String roomName, Panel chatWindowHolder,
      boolean compact, boolean anonymousInChatroom, boolean lazyCreation) {
   
    super(ureq, wControl);
    this.chatWindowHolder = chatWindowHolder;
    this.compact = compact;
    if (roomName == null) throw new AssertException("roomName can not be null");
    this.roomName = roomName;
    if (ores == null) throw new AssertException("olat resourcable can not be null");
    this.ores = ores;
    this.locale = ureq.getLocale();
    this.anonymousInChatroom = anonymousInChatroom;
    this.lazyCreation = lazyCreation;
    main = new Panel("main");
    openGroupChatPanel = LinkFactory.createCustomLink("participantsCount", "cmd.open.client", "", Link.NONTRANSLATED, summaryCompactVC, this);
   
    if (lazyCreation) { //show only link to join the groupChat
      openGroupChatPanel.setCustomDisplayText(getTranslator().translate("click.to.join"));
      openGroupChatPanel.setCustomEnabledLinkCSS("b_toolbox_link");
      openGroupChatPanel.setTooltip(getTranslator().translate("course.chat.click.to.join"), false);
      openGroupChatPanel.registerForMousePositionEvent(true);
      main.setContent(summaryCompactVC);
      putInitialPanel(main);
    } else {
     
      //create controller stuff and join chatRoom immediately
      if ( init(ureq) ) {
        putInitialPanel(main);
      } else {
        //error case
        putInitialPanel(errorCompact);
      }
     
    }
   
  }

  /**
   *
   * @param ureq
   */
  private boolean init(UserRequest ureq) {
    NICKNAME_ANONYMOUS = NICKNAME_PREFIX+(int)Math.rint(Math.random()*getIdentity().getKey());
    connection = InstantMessagingModule.getAdapter().getClientManager().getInstantMessagingClient(getIdentity().getName()).getConnection();
   
    roomJID = InstantMessagingModule.getAdapter().createChatRoomJID(ores);
    groupChatMsgPanel = new Panel("groupchat");
    roster = new Panel("roster");
    roster.setContent(rosterVC);
   
    messageHistory = new StringBuilder();
    groupchatVC.put("groupChatMessages", groupChatMsgPanel);
   
       
   
    if (compact) {
      openGroupChatPanel.setCustomDisplayText(1+" "+getTranslator().translate("participants.in.chat"));
      openGroupChatPanel.setCustomEnabledLinkCSS("b_toolbox_link");
      openGroupChatPanel.setTooltip(getTranslator().translate("course.chat.intro"), false);
      openGroupChatPanel.registerForMousePositionEvent(true);
      main.setContent(summaryCompactVC);
    } else {
      openGroupChatPanelButton = LinkFactory.createButton("openChat", summaryVC, this);
      openGroupChatPanelButton.registerForMousePositionEvent(true);
      summaryVC.put("roster", roster);
      main.setContent(summaryVC);
    }
   
   
    groupChatMsgPanel.setContent(groupChatMsgFieldVC);
    groupChatMsgFieldVC.contextPut("id", this.hashCode());
   
    //create form for username toogle
    toggleAnonymousForm = new ToggleAnonymousForm(ureq, getWindowControl());
    toggleAnonymousForm.addControllerListener(this);
    //toggle form only if logged in anonymous
    if (anonymousInChatroom) groupchatVC.put("toggleSwitch", toggleAnonymousForm.getInitialComponent());
   
    //create form for msg sending
    sendMessageForm = new SendMessageForm(ureq, getWindowControl());
    sendMessageForm.addControllerListener(this);
    groupchatVC.put("sendMessageForm", sendMessageForm.getInitialComponent());
   
    refresh = LinkFactory.createCustomLink("refresh", "cmd.refresh", "", Link.NONTRANSLATED, groupchatVC, this);
    refresh.setCustomEnabledLinkCSS("b_small_icon o_instantmessaging_refresh_icon");
    refresh.setTitle(getTranslator().translate("im.refresh"));
   
    Link refreshList = LinkFactory.createButtonXSmall("im.refresh", summaryVC, this);
   
   
    //set polling time of peridocal updater
    jsc = new JSAndCSSComponent("intervall2", this.getClass(), null, null, false, null, InstantMessagingModule.getIDLE_POLLTIME());
    groupchatVC.put("checkfordirtycomponents", jsc);
   
    //set defaults
    groupChatMsgFieldVC.contextPut("groupChatMessages", "");
    boolean ajaxOn = getWindowControl().getWindowBackOffice().getWindowManager().isAjaxEnabled();
    groupchatVC.contextPut("isAjaxMode", Boolean.valueOf(ajaxOn));
    summaryVC.contextPut("isAjaxMode", Boolean.valueOf(ajaxOn));
   
    if (connection != null && connection.isConnected()) {
      try {
        muc = new MultiUserChat(connection, roomJID);
        if (anonymousInChatroom) {
          roomJoinTask = new GroupChatJoinTask(ores, muc, connection, roomJID, NICKNAME_ANONYMOUS, sanitizeRoomName(roomName), this);
        } else {
          roomJoinTask = new GroupChatJoinTask(ores, muc, connection, roomJID, getIdentity().getName(), sanitizeRoomName(roomName), this);
          rosterVC.setDirty(true);
        }
        TaskExecutorManager.getInstance().runTask(roomJoinTask);
      } catch (IllegalStateException e) {
        logWarn("Error while trying to create group chat room for user"+getIdentity().getName()+" and course resource: +ores", e);
     
     
    } else {
      //error case
      return false;
    }
    initDone = true;
    return true;
  }

  /**
   * clean room name from ampersands
   * @param room
   * @return
   */
  private String sanitizeRoomName(String room) {
    if (room.contains("&")) {
      return room.replaceAll("&", "&amp;");
    }
    return room;
  }

  /**
   * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
   */
  @Override
  protected void doDispose() {
    //MUST be called by super controller!
    if (muc != null && muc.isJoined() && connection.isConnected()) {
      try {
        muc.leave();
    PacketListener msgListener = roomJoinTask.getMessageListener();
    if (msgListener != null) muc.removeMessageListener(msgListener);
    PacketListener pListener = roomJoinTask.getParticipationsListener();
    if (pListener != null) muc.removeParticipantListener(pListener);
    muc = null;
      } catch (Exception e) {
        logWarn("Error while leaving multiuserchat:", e);
      }     
    }
    if (toggleAnonymousForm != null) toggleAnonymousForm.dispose();
    if (sendMessageForm != null) sendMessageForm.dispose();
    if (floatingResizablePanelCtr != null ) floatingResizablePanelCtr.dispose();
   
  }

  /**
   * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
   *      org.olat.core.gui.components.Component,
   *      org.olat.core.gui.control.Event)
   */
  @Override
  public void event(UserRequest ureq, Component source, Event event) {
    if (lazyCreation && !initDone) {
      openGroupChatPanel.setCustomDisplayText(1+" "+getTranslator().translate("participants.in.chat"));
      openGroupChatPanel.setCustomEnabledLinkCSS("b_toolbox_link");
      openGroupChatPanel.setTooltip(getTranslator().translate("course.chat.intro"), false);
      openGroupChatPanel.registerForMousePositionEvent(true);
      init(ureq);
    }
   
    //offer refresh button for non ajax mode
    boolean ajaxOn = getWindowControl().getWindowBackOffice().getWindowManager().isAjaxEnabled();
    groupchatVC.contextPut("isAjaxMode", Boolean.valueOf(ajaxOn));
    summaryVC.contextPut("isAjaxMode", Boolean.valueOf(ajaxOn));
   
   
    if ( (muc != null && muc.isJoined())  ||  lazyCreation) {
      if (source == openGroupChatPanel || source == openGroupChatPanelButton || source == indicateNewMessage) {
      int x=0; int y=0;
      if (source == openGroupChatPanel) {
        x = openGroupChatPanel.getOffsetX()-450;
        y = openGroupChatPanel.getOffsetY()+30;
        if (x == -450 && y == 30) {x=300;y=300;} //selenium does not send xy coordinates -> set panel somewhere visible
      } else if (source == openGroupChatPanelButton) {
        x = openGroupChatPanelButton.getOffsetX();
        y = openGroupChatPanelButton.getOffsetY();
      } else if (source == indicateNewMessage) {
          x = indicateNewMessage.getOffsetX()-550;
          y = indicateNewMessage.getOffsetY();
      }
      //only open floating window if not yet open
      if (!chatWindowOpen) {
        if (floatingResizablePanelCtr != null ) floatingResizablePanelCtr.dispose();
        floatingResizablePanelCtr = new FloatingResizableDialogController(ureq, getWindowControl(), groupchatVC,
              getTranslator().translate("course.groupchat")+" "+roomNameShort(roomName), 550, 300, x, y, roster, getTranslator().translate("groupchat.roster"), true, false, true, "chat_window");
        floatingResizablePanelCtr.addControllerListener(this);
        jsc.setRefreshIntervall(InstantMessagingModule.getCHAT_POLLTIME());
         
        if (chatWindowHolder != null) {
          chatWindowHolder.setContent(floatingResizablePanelCtr.getInitialComponent());
        } else {
            main.setContent(floatingResizablePanelCtr.getInitialComponent());
        }
      }
      //reset new msg icon
      //indicateNewMessage.setCustomEnabledLinkCSS("");
      chatWindowOpen = true;
      prepareRosterList();
      groupchatVC.contextPut("title", roomNameShort(roomName));
      if (indicateNewMessage != null) indicateNewMessage.setCustomEnabledLinkCSS("");
       
    }
    } else {
      if (compact) {
        main.setContent(errorCompact);
      } else {
        main.setContent(error);
      }
    }
   
  }
 
  private String roomNameShort(String roomNameLong) {
    if (roomNameLong.length() > 30) return roomNameLong.substring(0, 29)+"...";
    return roomNameLong;
  }



  /**
   *
   * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
   */
  @Override
  protected void event(UserRequest ureq, Controller source, Event event) {
    //TODO:gs:a wrap also muc, to catch all exceptions which can occur
    if (muc != null && muc.isJoined()) {
      try {
        if (source == toggleAnonymousForm) {
            if (muc.getNickname().startsWith(NICKNAME_PREFIX)) {
                try {
                  muc.changeNickname(getIdentity().getName());
                } catch (XMPPException e) {
                  logWarn("Could not change nickname for user: "+getIdentity().getName() + "in course chat: "+ores, e);
                  appendToMsgHistory(createMessage("chatroom", getTranslator().translate("msg.send.error")));
                } catch (Exception e) {
                  logWarn("Could not change nickname for user: "+getIdentity().getName() + "in course chat: "+ores, e);
                  appendToMsgHistory(createMessage("chatroom", getTranslator().translate("msg.send.error")));
                }
            }
            else {
              muc.changeNickname(NICKNAME_ANONYMOUS);
            }
        } else if (source == sendMessageForm) {
          if (isLogDebugEnabled()) logDebug("sending msg: +"+sendMessageForm.getMessage()+ "+ to chatroom: "+roomJID, null);
            try {
              muc.sendMessage(sendMessageForm.getMessage());
              sendMessageForm.resetTextField();
            } catch (XMPPException e) {
              logWarn("Could not send IM message for user: "+getIdentity().getName() + "in course chat: "+ores, e);
              appendToMsgHistory(createMessage("chatroom", getTranslator().translate("msg.send.error")));
            }
        }
        //hack, IM server need some time to send msg to client. Only an issue in non ajax mode
        //otherwise the user can't see the message he has just send
        boolean ajaxOn = getWindowControl().getWindowBackOffice().getWindowManager().isAjaxEnabled();
        if (!ajaxOn) {
          try {
            Thread.sleep(100);
          } catch (InterruptedException e) {
            //nothing to do
          }
        }
      } catch (XMPPException e) {
        logWarn("Could not send IM message for user: "+getIdentity().getName() + "in course chat: "+ores, e);
        appendToMsgHistory(createMessage("chatroom", getTranslator().translate("msg.send.error")));
      } catch (IllegalStateException e) {
        //this happens when the server is going down while the user had already joind a room and tries to send a msg
        logWarn("Could not send IM message for user: "+getIdentity().getName() + "in course chat: "+ores, e);
        appendToMsgHistory(createMessage("chatroom", getTranslator().translate("msg.send.error")));
      }
     
      groupChatMsgFieldVC.setDirty(true);//set dirty for non ajax mode
      rosterVC.setDirty(true);//set dirty for non ajax mode
      occupantsCount = Integer.valueOf(muc.getOccupantsCount());
      if (occupantsCount.equals(Integer.valueOf(0))) occupantsCount = Integer.valueOf(1);
      openGroupChatPanel.setCustomDisplayText(occupantsCount+" "+getTranslator().translate("participants.in.chat"));
     
    } else {
      Message msg = createMessage("chatroom", getTranslator().translate("coursechat.not.available"));
      appendToMsgHistory(msg);
      main.setContent(errorCompact);
    }
    if (source == floatingResizablePanelCtr) {
      if (chatWindowHolder != null) {
        chatWindowHolder.setContent(null);
      } else {
        if (compact) main.setContent(summaryCompactVC);
        else main.setContent(summaryVC);
      }
     
      if (indicateNewMessage != null) {
        summaryCompactVC.remove(indicateNewMessage);
        indicateNewMessage = null;
      }
      chatWindowOpen = false;
     
      //decrease polling time of periodical updater
      jsc.setRefreshIntervall(InstantMessagingModule.getIDLE_POLLTIME());
    }
  }

  /**
   * @return true if the chat window is openend by the user
   * used by velocity
   */
  public boolean isChatWindowOpen() {
    return chatWindowOpen;
  }

  private Message createMessage(String from, String msgBody) {
    Message msg = new Message();
    msg.setBody(msgBody);
    msg.setFrom(from);
    msg.setProperty("receiveTime", new Long(new Date().getTime()));
    return msg;
  }
 
  public void event(Event event) {
    InstantMessagingEvent imEvent = (InstantMessagingEvent)event;
    if (imEvent.getCommand().equals("groupchat")) {
      Message msg = (Message) imEvent.getPacket();
      if (isLogDebugEnabled()) logDebug("incoming msg for groupchat: "+msg.getType(), null);
      msg.setProperty("receiveTime", new Long(new Date().getTime()));
      if ((msg.getType() == Message.Type.groupchat) && msg.getBody() != null) {
        if (!chatWindowOpen && !msg.getBody().startsWith("This room is")) { //get rid of room status msg                   
          indicateNewMessage  = LinkFactory.createCustomLink("indicateNewMsg", "cmd.open.client", "&nbsp;", Link.NONTRANSLATED, summaryCompactVC, this);
          indicateNewMessage.registerForMousePositionEvent(true);
          indicateNewMessage.setCustomEnabledLinkCSS("b_small_icon o_instantmessaging_new_msg_icon");
          indicateNewMessage.setTooltip(getTranslator().translate("groupchat.new.msg"), true);
        }
          appendToMsgHistory(msg);
      }
    } else if (imEvent.getCommand().equals("participant")) {
      Presence presence = (Presence) imEvent.getPacket();
      if (isLogDebugEnabled()) logDebug("incoming presence change for groupchat: "+presence.getFrom() +" : "+ presence.getType(), null);
     
      if (presence.getFrom() != null) {
        if (presence.getFrom().startsWith("coursemodule-") && presence.getType() == Presence.Type.unavailable && !presence.getFrom().endsWith(NICKNAME_ANONYMOUS)) {
          //workaround for smack bug, that does not instantly update the occupants count when someone leaves the room
          if (occupantsCount != 1) occupantsCount--;
        } else {
        occupantsCount = Integer.valueOf(muc.getOccupantsCount());
          if (occupantsCount.equals(Integer.valueOf(0))) occupantsCount = Integer.valueOf(1);
        }
        if (isLogDebugEnabled()) logDebug("incoming presence change for groupchat. No. of participants: "+occupantsCount, null);
        openGroupChatPanel.setCustomDisplayText(occupantsCount+" "+getTranslator().translate("participants.in.chat"));
        try {
          if (chatWindowOpen) {
            //FIXME:gs:a temporary fox for connection increasing problem due to asynchronous nature of IM events
            // together with <hibernate.c3p0.autoCommitOnClose>false</hibernate.c3p0.autoCommitOnClose> switch it showed up
            prepareRosterList(presence);
            DBFactory.getInstance(false).commitAndCloseSession();
          }
        } catch (Exception e) {
          DBFactory.getInstance(false).rollbackAndCloseSession();
        }
      }
    }
   
  }



  private void appendToMsgHistory(Message msg) {
    if(!msg.getBody().startsWith("This room is")) {
      synchronized (messageHistory) {  // //o_clusterOK by:fj: message history is per user
        messageHistory.append("<div><span style=\"color:"+colorizeUserName(extractUsername(msg.getFrom()))+"\">[");
        messageHistory.append(ClientHelper.getSendDate(msg, locale));
        messageHistory.append("] ");
        messageHistory.append(extractUsername(msg.getFrom()));
        messageHistory.append(": </span>");
        messageHistory.append(msg.getBody());
        messageHistory.append("</div>");
        groupChatMsgFieldVC.contextPut("groupChatMessages", messageHistory.toString());
      }
    }
  }
 
  /**
   *
   * @param presence
   */
  private void prepareRosterList(Presence presence) {
    synchronized (rosterList) {  //o_clusterOK by:fj
      if (presence.getType() == Presence.Type.available) {

        if (!rosterList.contains(extractUsername(presence.getFrom()))) {
          rosterList.add(getFullUserName(extractUsername(presence.getFrom())));
        }
      } else if (presence.getType() == Presence.Type.unavailable) {
        rosterList.remove(getFullUserName(extractUsername(presence.getFrom())));
      }
    }
   
    rosterVC.contextPut("rosterList", rosterList);
  }
 
  /**
   *
   * @param username
   * @return full user name and username of user like Guido Schnider (guidosch)
   * or the username if not found
   *
   */
  private String getFullUserName(String username) {
    Identity ident = ManagerFactory.getManager().findIdentityByName(username);
    if (ident != null) {
      StringBuilder sb = new StringBuilder();
      sb.append(ident.getUser().getProperty(UserConstants.FIRSTNAME, locale)).append(" ");
      sb.append(ident.getUser().getProperty(UserConstants.LASTNAME, locale)).append(" ");
      sb.append("(").append(ident.getName()).append(")");
      return sb.toString();
    }
    return username;
  }
 
  private void prepareRosterList() {
    //there are many incoming events for a groupchat, only update the roster with a break of five seconds
    if (System.currentTimeMillis()-latestRosterUpdate > 2000) {
      rosterList = new ArrayList<String>();
      latestRosterUpdate  = System.currentTimeMillis();
      try {
        for (Iterator i = muc.getOccupants(); i.hasNext();) {
          String occupant = (String) i.next();
            rosterList.add(getFullUserName(extractUsername(occupant)));
        }
        if ( rosterList.size() == 0 ) {
          rosterList.add(NICKNAME_ANONYMOUS);
        }
        rosterVC.contextPut("rosterList", rosterList);
      } catch (Exception e) {
        logWarn("Error while trying to get participants for chat room for user"+getIdentity().getName()+" and course resource: +ores", e);
     
    }
  }

  private String colorizeUserName(String from) {
    //append name to lengt 6
    if (from.startsWith(NICKNAME_PREFIX)) {
      from = new StringBuilder(from).reverse().toString();
    }
   
    if (from.length() < 6){
      while (from.length() < 6) {
        from = from+"9";
      }
    }
    //get hex form the first 6 chars (only numbers)
    StringBuilder sb = new StringBuilder();
    sb.append("#");
    for (int j = 0; j < 6; j++) {
      int z = from.charAt(j)%9;
      if(z == 8) sb.append("A");//make more darker colors
      else if (z == 9) sb.append("B");
      else sb.append(z);
    }
    return sb.toString();
  }



  private String extractUsername(String from) {
    if(from != null) {
      if(from.contains("/"))
        return from.substring(from.lastIndexOf("/")+1, from.length());
    }
    return "chatroom";
  }

}
TOP

Related Classes of org.olat.instantMessaging.groupchat.InstantMessagingGroupChatController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.