/** * $RCSfile: ,v $ * $Revision: $ * $Date: $ * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jivesoftware.fastpath.workspace.panes; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.jivesoftware.fastpath.FastpathPlugin; import org.jivesoftware.fastpath.FpRes; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.Form; import org.jivesoftware.smackx.muc.Affiliate; import org.jivesoftware.smackx.muc.MultiUserChat; import org.jivesoftware.smackx.workgroup.agent.AgentRoster; import org.jivesoftware.smackx.workgroup.agent.AgentRosterListener; import org.jivesoftware.smackx.workgroup.packet.AgentStatus; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.tabbedPane.SparkTab; import org.jivesoftware.spark.component.tabbedPane.SparkTabbedPaneListener; import org.jivesoftware.spark.ui.conferences.ConferenceUtils; import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.SwingWorker; import org.jivesoftware.spark.util.log.Log; import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; import org.jivesoftware.sparkimpl.settings.local.SettingsManager; /** * UI to show all chats occuring. */ public final class AgentConversations extends JPanel implements ChangeListener { private static final long serialVersionUID = 1L; private DefaultListModel model = new DefaultListModel(); private JList list; private Map<String, AgentConversation> sessionMap = new HashMap<String, AgentConversation>(); /** * Add listeners and construct UI. */ public AgentConversations() { FastpathPlugin.getUI().getMainPanel().addSparkTabbedPaneListener(new SparkTabbedPaneListener() { public void tabRemoved(SparkTab tab, Component component, int index) { } public void tabAdded(SparkTab tab, Component component, int index) { } public void tabSelected(SparkTab tab, Component component, int index) { stateChanged(null); } public void allTabsRemoved() { } public boolean canTabClose(SparkTab tab, Component component) { return true; } }); } private void init() { list = new JList(model); this.setLayout(new BorderLayout()); this.setBackground(Color.white); this.setForeground(Color.white); JScrollPane scrollPane = new JScrollPane(list); scrollPane.setBorder(BorderFactory.createEmptyBorder()); this.add(scrollPane, BorderLayout.CENTER); list.setCellRenderer(new FastpathPanelRenderer()); list.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent mouseEvent) { int index = list.locationToIndex(mouseEvent.getPoint()); list.setSelectedIndex(index); checkPopup(mouseEvent); } public void mouseReleased(MouseEvent mouseEvent) { int index = list.locationToIndex(mouseEvent.getPoint()); list.setSelectedIndex(index); checkPopup(mouseEvent); } }); } private void addAgentChat(String agentID, String name, String email, String question, Date startDate, String sessionID) { if (sessionMap.containsKey(sessionID)) { return; } AgentConversation item = new AgentConversation(agentID, name, startDate, email, question, sessionID); model.addElement(item); sessionMap.put(sessionID, item); } private void removeConversation(String sessionID) { AgentConversation item = sessionMap.get(sessionID); if (item != null) { model.removeElement(item); } } public void stateChanged(ChangeEvent e) { if (FastpathPlugin.getUI().getMainPanel().getSelectedComponent() == this && list == null) { init(); SwingWorker agentWorker = new SwingWorker() { AgentRoster agentRoster; Collection agentSet; public Object construct() { agentRoster = FastpathPlugin.getAgentSession().getAgentRoster(); agentSet = agentRoster.getAgents(); return agentSet; } public void finished() { agentRoster.addListener(new AgentRosterListener() { public void agentAdded(String jid) { } public void agentRemoved(String jid) { } public void presenceChanged(Presence presence) { String agentJID = StringUtils.parseBareAddress(presence.getFrom()); AgentStatus agentStatus = (AgentStatus)presence.getExtension("agent-status", "http://jabber.org/protocol/workgroup"); String status = presence.getStatus(); if (status == null) { status = "Available"; } if (agentStatus != null) { List list = agentStatus.getCurrentChats(); removeOldChats(agentJID, list); // Add new ones. Iterator iter = list.iterator(); while (iter.hasNext()) { AgentStatus.ChatInfo chatInfo = (AgentStatus.ChatInfo)iter.next(); Date startDate = chatInfo.getDate(); String username = chatInfo.getUserID(); String nickname = chatInfo.getUsername(); if (!ModelUtil.hasLength(nickname)) { nickname = "Not specified"; } String question = chatInfo.getQuestion(); if (!ModelUtil.hasLength(question)) { question = "No question asked"; } String email = chatInfo.getEmail(); if (!ModelUtil.hasLength(email)) { email = "Not specified"; } addAgentChat(agentJID, nickname, email, question, startDate, chatInfo.getSessionID()); } } calculateNumberOfChats(agentRoster); } }); } }; agentWorker.start(); } } private void calculateNumberOfChats(AgentRoster agentRoster) { int counter = 0; // TODO: CHECK FASTPATH //for (String agent : agentRoster.getAgents()) { for (Iterator it = agentRoster.getAgents().iterator(); it.hasNext();) { String agent = (String)it.next(); Presence presence = agentRoster.getPresence(agent); if (presence.isAvailable()) { AgentStatus agentStatus = (AgentStatus)presence.getExtension("agent-status", "http://jabber.org/protocol/workgroup"); if (agentStatus != null) { counter += agentStatus.getCurrentChats().size(); } } } FastpathPlugin.getUI().setTitleForComponent(FpRes.getString("message.current.chats", counter), this); } private boolean newListHasSession(String sessionID, List chatList) { // Add new ones. Iterator iter = chatList.iterator(); while (iter.hasNext()) { AgentStatus.ChatInfo chatInfo = (AgentStatus.ChatInfo)iter.next(); String session = chatInfo.getSessionID(); if (session.equalsIgnoreCase(sessionID)) { return true; } } return false; } private void removeOldChats(String agentJID, List chatList) { for (AgentConversation agent : sessionMap.values()) { if (agent.getAgentJID().equals(agentJID)) { String sessionID = agent.getSessionID(); boolean listHasID = newListHasSession(sessionID, chatList); if (!listHasID) { removeConversation(sessionID); } } } } private void checkPopup(MouseEvent e) { if (e.isPopupTrigger()) { // Check if monitor try { AgentConversation item = (AgentConversation)list.getSelectedValue(); boolean isMonitor = FastpathPlugin.getAgentSession().hasMonitorPrivileges(SparkManager.getConnection()); if (isMonitor) { JPopupMenu menu = new JPopupMenu(); final String sessionID = item.getSessionID(); Action joinAction = new AbstractAction() { private static final long serialVersionUID = 8239167390330425891L; public void actionPerformed(ActionEvent actionEvent) { // Get Conference try { Collection col = MultiUserChat.getServiceNames(SparkManager.getConnection()); if (col.size() == 0) { return; } String serviceName = (String)col.iterator().next(); String roomName = sessionID + "@" + serviceName; LocalPreferences pref = SettingsManager.getLocalPreferences(); final String nickname = pref.getNickname(); MultiUserChat muc = new MultiUserChat(SparkManager.getConnection(), roomName); ConferenceUtils.enterRoom(muc, roomName, nickname, null); if (muc.isJoined()) { // Try and remove myself as an owner if I am one. Collection owners = null; try { owners = muc.getOwners(); } catch (XMPPException e1) { return; } Iterator iter = owners.iterator(); List<String> list = new ArrayList<String>(); while (iter.hasNext()) { Affiliate affilitate = (Affiliate)iter.next(); String jid = affilitate.getJid(); if (!jid.equals(SparkManager.getSessionManager().getBareAddress())) { list.add(jid); } } if (list.size() > 0) { Form form = muc.getConfigurationForm().createAnswerForm(); form.setAnswer("muc#roomconfig_roomowners", list); // new DataFormDialog(groupChat, form); muc.sendConfigurationForm(form); } } } catch (Exception e1) { Log.error(e1); } } }; joinAction.putValue(Action.NAME, FpRes.getString("menuitem.join.chat")); menu.add(joinAction); Action monitorAction = new AbstractAction() { private static final long serialVersionUID = -2072254190661466657L; public void actionPerformed(ActionEvent actionEvent) { // Make user an owner. try { FastpathPlugin.getAgentSession().makeRoomOwner(SparkManager.getConnection(), sessionID); Collection<String> col = MultiUserChat.getServiceNames(SparkManager.getConnection()); if (col.size() == 0) { return; } String serviceName = (String)col.iterator().next(); String roomName = sessionID + "@" + serviceName; LocalPreferences pref = SettingsManager.getLocalPreferences(); final String nickname = pref.getNickname(); MultiUserChat muc = new MultiUserChat(SparkManager.getConnection(), roomName); ConferenceUtils.enterRoom(muc, roomName, nickname, null); } catch (XMPPException e1) { Log.error(e1); } } }; monitorAction.putValue(Action.NAME, FpRes.getString("menuitem.monitor.chat")); menu.add(monitorAction); menu.show(list, e.getX(), e.getY()); } } catch (XMPPException e1) { Log.error(e1); return; } } } }