/** * $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.invite; import java.awt.BorderLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import org.jivesoftware.fastpath.FastpathPlugin; import org.jivesoftware.fastpath.FpRes; import org.jivesoftware.fastpath.resources.FastpathRes; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.workgroup.agent.Agent; import org.jivesoftware.smackx.workgroup.agent.AgentRoster; import org.jivesoftware.smackx.workgroup.agent.WorkgroupQueue; import org.jivesoftware.spark.PresenceManager; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.UserManager; import org.jivesoftware.spark.component.JiveTreeCellRenderer; import org.jivesoftware.spark.component.JiveTreeNode; import org.jivesoftware.spark.component.TitlePanel; import org.jivesoftware.spark.component.Tree; import org.jivesoftware.spark.ui.ChatRoom; import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.ResourceUtils; import org.jivesoftware.spark.util.log.Log; /** * UI and Dialog to show all available agents that can be invited into a ChatRoom. */ public class WorkgroupInvitationDialog implements PropertyChangeListener { private Tree tree; private Tree rosterTree; private WorkgroupRosterTree roster; private JiveTreeNode rootNode; private JOptionPane pane; private JDialog dlg; private boolean isValid; private TitlePanel titlePanel; private JTextArea messageField; private JTextField jidField = new JTextField(); private List workgroups = new ArrayList(); private JLabel inviteLabel; /** * Empty Constructor. */ public WorkgroupInvitationDialog() { } /** * Returns the agent selected. * * @param chatRoom the room this roster will be used with. * @param transfer true if this will be a transfer. * @return true if a valid agent has been selected. */ public boolean hasSelectedAgent(ChatRoom chatRoom, boolean transfer) { final JiveTreeNode workgroupsNode = new JiveTreeNode("Workgroups", true); final JiveTreeNode queueNode = new JiveTreeNode("Queues", true); final String workgroupService = "workgroup." + SparkManager.getSessionManager().getServerAddress(); final String jid = SparkManager.getSessionManager().getJID(); String room = chatRoom.getRoomname(); Collection agents = getAvailableAgents(FastpathPlugin.getAgentSession().getAgentRoster(), room); // Clear jid field jidField.setText(""); String title = FpRes.getString("invite.agent"); String acceptButton = FpRes.getString("invite"); if (transfer) { title = FpRes.getString("transfer.to.agent"); acceptButton = FpRes.getString("transfer"); } String stockMessage = FpRes.getString("message.transfering.to.user"); if (!transfer) { stockMessage = FpRes.getString("message.join.me.in.chat"); } rootNode = new JiveTreeNode("Ask For Assistance", true); tree = new Tree(rootNode); tree.setCellRenderer(new JiveTreeCellRenderer()); // This will remove lines from the tree and setup initial l&f tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); tree.setRowHeight(16); tree.setExpandsSelectedPaths(true); tree.addTreeSelectionListener(new TreeSelectionListener() { public void valueChanged(TreeSelectionEvent e) { TreePath path = e.getNewLeadSelectionPath(); Object o = path.getLastPathComponent(); if (o instanceof JiveTreeNode) { JiveTreeNode node = (JiveTreeNode)o; JiveTreeNode parentNode = (JiveTreeNode)node.getParent(); if (parentNode == workgroupsNode) { jidField.setText(node.getUserObject().toString() + "@" + workgroupService); } else if (parentNode == queueNode) { jidField.setText(FastpathPlugin.getWorkgroup().getWorkgroupJID() + "/" + node.getUserObject().toString()); } else { String agent = getAgent(); jidField.setText(agent); } } } }); // Create message field messageField = new JTextArea(); messageField.setWrapStyleWord(true); inviteLabel = new JLabel(); if (transfer) { inviteLabel.setText(FpRes.getString("transfer.to") + ":"); } else { inviteLabel.setText(FpRes.getString("invite") + ":"); } if (transfer) { // Create the title panel for this dialog titlePanel = new TitlePanel(FpRes.getString("title.transfer"), FpRes.getString("message.transfer.to.another.agent"), FastpathRes.getImageIcon(FastpathRes.CHATTING_AGENT_IMAGE), true); } else { // Create the title panel for this dialog titlePanel = new TitlePanel(FpRes.getString("title.invitation"), FpRes.getString("message.invite.another.agent"), FastpathRes.getImageIcon(FastpathRes.CHATTING_AGENT_IMAGE), true); } // Build Tree String joinedWorkgroupName = StringUtils.parseName(FastpathPlugin.getWorkgroup().getWorkgroupJID()); final JiveTreeNode workgroupNode = new JiveTreeNode(joinedWorkgroupName, true); final Iterator agentIter = agents.iterator(); while (agentIter.hasNext()) { while (agentIter.hasNext()) { String agentName = UserManager.unescapeJID((String)agentIter.next()); final JiveTreeNode agentNode = new JiveTreeNode(agentName, false, FastpathRes.getImageIcon(FastpathRes.GREEN_BALL)); workgroupNode.add(agentNode); } if (workgroupNode.getChildCount() > 0) { rootNode.add(workgroupNode); } } Collection workgroupAgents; try { workgroupAgents = Agent.getWorkgroups(workgroupService, jid, SparkManager.getConnection()); } catch (XMPPException e) { Log.error(e); workgroupAgents = Collections.EMPTY_LIST; } if (workgroupAgents.size() > 0) { // Add workgroups to combobox Iterator<String> workgroups = workgroupAgents.iterator(); while (workgroups.hasNext()) { String workgroup = workgroups.next(); String workgroupName = StringUtils.parseName(workgroup); final JiveTreeNode wgNode = new JiveTreeNode(workgroupName, false, FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_16x16)); workgroupsNode.add(wgNode); } rootNode.add(workgroupsNode); } Iterator iter = FastpathPlugin.getAgentSession().getQueues(); while (iter.hasNext()) { final WorkgroupQueue queue = (WorkgroupQueue)iter.next(); if (queue.getStatus() == WorkgroupQueue.Status.OPEN) { final JiveTreeNode qNode = new JiveTreeNode(queue.getName(), false, FastpathRes.getImageIcon(FastpathRes.FASTPATH_IMAGE_16x16)); queueNode.add(qNode); } } rootNode.add(queueNode); // New Roster tree. Do not show agents at all. final UserManager userManager = SparkManager.getUserManager(); Collection jids = userManager.getUserJidsInRoom(room, false); roster = new WorkgroupRosterTree(jids, false, workgroups); try { rosterTree = roster.getRosterTree(); JiveTreeNode node = (JiveTreeNode)rosterTree.getModel().getRoot(); rootNode.add(node); } catch (Exception e) { Log.error("Error checking for selected agent", e); } // Construct main panel w/ layout. final JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout()); mainPanel.add(titlePanel, BorderLayout.NORTH); // The user should only be able to close this dialog. Object[] options = {acceptButton, FpRes.getString("cancel")}; // Create objects to add to mainPanel. final JPanel parentPanel = new JPanel(); final JLabel messageLabel = new JLabel(); final JLabel agentLabel = new JLabel(); parentPanel.setLayout(new GridBagLayout()); // Update Labels using ResourceUtils ResourceUtils.resLabel(messageLabel, messageField, FpRes.getString("label.message.to.agent")); ResourceUtils.resLabel(agentLabel, tree, FpRes.getString("label.select.agent")); // Add Components to Parent Panel parentPanel.add(agentLabel, new GridBagConstraints(0, 0, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 5), 0, 0)); parentPanel.add(new JScrollPane(tree), new GridBagConstraints(0, 1, 3, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 100)); parentPanel.add(messageLabel, new GridBagConstraints(0, 3, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 5), 0, 0)); parentPanel.add(new JScrollPane(messageField), new GridBagConstraints(0, 4, 3, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 25)); parentPanel.add(inviteLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); parentPanel.add(jidField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); // Use line wrap. messageField.setLineWrap(true); // Update MessageField with stock message messageField.setText(stockMessage); // Add Parent Object to master OptionPane pane = new JOptionPane(parentPanel, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); mainPanel.add(pane, BorderLayout.CENTER); dlg = new JDialog(SparkManager.getChatManager().getChatContainer().getChatFrame(), title, true); dlg.pack(); dlg.setSize(500, 500); dlg.setContentPane(mainPanel); dlg.setLocationRelativeTo(chatRoom); pane.addPropertyChangeListener(this); // expand the tree for displaying for (int i = 0; i <= tree.getRowCount(); i++) { tree.expandPath(tree.getPathForRow(i)); } dlg.setVisible(true); dlg.toFront(); dlg.requestFocus(); if (!isValid) { return false; } return true; } public void propertyChange(PropertyChangeEvent e) { String value = (String)pane.getValue(); if (FpRes.getString("cancel").equals(value)) { isValid = false; dlg.setVisible(false); } else if (FpRes.getString("invite").equals(value) || FpRes.getString("transfer").equals(value)) { String agent = jidField.getText(); boolean isValidJID = agent.indexOf("@") != -1; if (!ModelUtil.hasLength(agent)) { JOptionPane.showMessageDialog(dlg, FpRes.getString("message.no.agent.selected.error"), FpRes.getString("error"), JOptionPane.ERROR_MESSAGE); pane.setValue(JOptionPane.UNINITIALIZED_VALUE); } else if (!isValidJID) { JOptionPane.showMessageDialog(dlg, FpRes.getString("message.jid.invalid.error"), FpRes.getString("title.error"), JOptionPane.ERROR_MESSAGE); pane.setValue(JOptionPane.UNINITIALIZED_VALUE); } else if (!ModelUtil.hasLength(getMessage())) { JOptionPane.showMessageDialog(dlg, FpRes.getString("message.message.required.error"), FpRes.getString("title.error"), JOptionPane.ERROR_MESSAGE); pane.setValue(JOptionPane.UNINITIALIZED_VALUE); } else { isValid = true; dlg.setVisible(false); } } } /** * Return the message to send to the agent. * * @return the message to send to the agent. */ public String getMessage() { return messageField.getText(); } /** * Returns the selected jid to transfer to. * * @return the selected jid. */ public String getSelectedJID() { return jidField.getText(); } /** * Handles tree selection of an agent. * * @return the agents jid. */ private String getAgent() { String agentJID; final DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(); if (node == null || node.getAllowsChildren()) { return ""; } agentJID = roster.getAgentJID((JiveTreeNode)node); if (agentJID == null) { final Object nodeInfo = node.getUserObject(); if (!node.isLeaf()) { return ""; } agentJID = nodeInfo.toString(); } return agentJID; } /** * Returns a Collection of agents available to receive either an invitation or transfer request. * * @param roster the AgentRoster of the workgroup. * @param roomName the name of the room to check. * @return collection of available agents. */ private Collection<String> getAvailableAgents(AgentRoster roster, String roomName) { final Set<String> availableAgents = new HashSet<String>(); final Iterator<String> agents = roster.getAgents().iterator(); while (agents.hasNext()) { String agent = agents.next(); if (PresenceManager.isAvailable(agent)) { final Iterator agentsInRoom = SparkManager.getUserManager().getUserJidsInRoom(roomName, false).iterator(); boolean alreadyExists = false; while (agentsInRoom.hasNext()) { String userid = (String)agentsInRoom.next(); if (agent.equalsIgnoreCase(userid)) { alreadyExists = true; } } if (!alreadyExists) { availableAgents.add(agent); } } } return availableAgents; } }