001    /*
002     *  Copyright (C) 2003 Adam Olsen
003     *  This program is free software; you can redistribute it and/or modify
004     *  it under the terms of the GNU General Public License as published by
005     *  the Free Software Foundation; either version 1, or (at your option)
006     *  any later version.
007     *  This program is distributed in the hope that it will be useful,
008     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
009     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
010     *  GNU General Public License for more details.
011     *  You should have received a copy of the GNU General Public License
012     *  along with this program; if not, write to the Free Software
013     *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
014     */
015    package com.valhalla.jbother;
016    
017    import java.awt.Container;
018    import java.awt.GridBagConstraints;
019    import java.awt.GridBagLayout;
020    import java.awt.event.ActionEvent;
021    import java.awt.event.ActionListener;
022    import java.awt.event.ItemEvent;
023    import java.awt.event.ItemListener;
024    import java.awt.event.WindowAdapter;
025    import java.awt.event.WindowEvent;
026    import java.util.Iterator;
027    import java.util.Locale;
028    import java.util.ResourceBundle;
029    
030    import javax.swing.BorderFactory;
031    import javax.swing.BoxLayout;
032    import javax.swing.DefaultComboBoxModel;
033    import javax.swing.JButton;
034    import javax.swing.JComboBox;
035    import javax.swing.JDialog;
036    import javax.swing.JFrame;
037    import javax.swing.JLabel;
038    import javax.swing.JPanel;
039    import javax.swing.SwingUtilities;
040    
041    import org.jivesoftware.smack.Roster;
042    import org.jivesoftware.smack.RosterEntry;
043    import org.jivesoftware.smack.RosterGroup;
044    import org.jivesoftware.smack.XMPPException;
045    
046    import com.valhalla.gui.DialogTracker;
047    import com.valhalla.gui.MJTextField;
048    import com.valhalla.gui.NMOptionDialog;
049    import com.valhalla.gui.Standard;
050    import com.valhalla.gui.WaitDialog;
051    import com.valhalla.jbother.jabber.BuddyStatus;
052    
053    /**
054     *  Displays a dialog allowing to you add or modify a buddy. It displays their
055     *  JID, Alias, and group
056     *
057     *@author     Adam Olsen
058     *@created    September 26, 2005
059     *@version    1.0
060     */
061    public class AddBuddyDialog extends JDialog {
062        private ResourceBundle resources = ResourceBundle.getBundle(
063                "JBotherBundle", Locale.getDefault());
064    
065        private JComboBox buddyGroups;
066    
067        private MJTextField buddyIDBox = new MJTextField(20);
068    
069        private MJTextField buddyAliasBox = new MJTextField(20);
070    
071        private MJTextField newGroupBox;
072    
073        private JPanel container = new JPanel();
074    
075        private RosterEntry entry;
076    
077        private String currentGroup = "";
078    
079        //the buttons
080        private JButton okButton = new JButton(resources.getString("okButton"));
081    
082        private JButton cancelButton = new JButton(resources.getString("cancelButton"));
083    
084        //this part is for laying out the rows for the dialog
085        private int row = 0;
086    
087        private GridBagLayout grid = new GridBagLayout();
088    
089        private GridBagConstraints c = new GridBagConstraints();
090    
091        private boolean modify = false;
092    
093    
094        /**
095         *  The add buddy constructor
096         */
097        public AddBuddyDialog() {
098            super(BuddyList.getInstance().getContainerFrame(), "Add/Modify Buddy", false);
099            setTitle(resources.getString("addBuddyDialogTitle"));
100    
101            this.initComponents();
102            container.setBorder(BorderFactory.createEmptyBorder(5, 25, 5, 25));
103            container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
104    
105            JLabel newBuddyLabel = new JLabel(resources.getString("addBuddyDialogTitle"));
106            newBuddyLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
107            newBuddyLabel.setAlignmentX(Container.CENTER_ALIGNMENT);
108            container.add(newBuddyLabel);
109    
110            JPanel newBuddyPanel = new JPanel();
111            newBuddyPanel.setLayout(grid);
112    
113            createInputBox(newBuddyPanel, grid, resources.getString("buddyId")
114                     + ":", buddyIDBox);
115            createInputBox(newBuddyPanel, grid, resources.getString("alias") + ":",
116                    buddyAliasBox);
117            createInputBox(newBuddyPanel, grid, resources.getString("buddyGroup")
118                     + ":", buddyGroups);
119            createInputBox(newBuddyPanel, grid, resources.getString("newGroup")
120                     + ":", newGroupBox);
121    
122            container.add(newBuddyPanel);
123    
124            //add the buttons
125            JPanel buttonPanel = new JPanel();
126            buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
127            buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
128            buttonPanel.add(okButton);
129            buttonPanel.add(cancelButton);
130    
131            container.add(buttonPanel);
132    
133            DialogTracker.addDialog(this, true, true);
134            setResizable(false);
135    
136            pack();
137            setLocationRelativeTo(null);
138    
139        }
140    
141    
142        /**
143         *  Destroys the dialog
144         */
145        public void delete() {
146            DialogTracker.removeDialog(this);
147        }
148    
149    
150        /**
151         *  The modify buddy constructor
152         *
153         *@param  entry  the entry to modify
154         */
155        public void setBuddy(RosterEntry entry) {
156            this.entry = entry;
157            this.buddyIDBox.setText(entry.getUser());
158            this.buddyIDBox.setEnabled(false);
159            this.modify = true;
160            this.buddyAliasBox.setText(entry.getName());
161    
162            String currentGroup = "";
163    
164            Iterator iterator = entry.getGroups();
165            while (iterator.hasNext()) {
166                RosterGroup group = (RosterGroup) iterator.next();
167                currentGroup = group.getName();
168            }
169    
170            if (!currentGroup.equals("")) {
171                this.currentGroup = currentGroup;
172            }
173    
174            //buddyGroups = new JComboBox( getRosterGroups() );
175            buddyGroups.setModel(new DefaultComboBoxModel(getRosterGroups()));
176    
177            validate();
178        }
179    
180    
181        /**
182         *  Called by the cancel button - destroys the dialog
183         */
184        private void cancelButtonHandler() {
185            DialogTracker.removeDialog(this);
186        }
187    
188    
189        /**
190         *  Sets the JID in the dialog
191         *
192         *@param  id  the JID
193         */
194        public void setBuddyId(String id) {
195            buddyIDBox.setText(id);
196            validate();
197        }
198    
199    
200        /**
201         *  Sets up visual components
202         */
203        private void initComponents() {
204            setContentPane(container);
205            buddyGroups = new JComboBox(getRosterGroups());
206            newGroupBox = new MJTextField(15);
207            newGroupBox.setText(resources.getString("newGroup"));
208            newGroupBox.setEnabled(false);
209    
210            //add the handlers
211            cancelButton.addActionListener(new ActionHandler());
212            okButton.addActionListener(new ActionHandler());
213            newGroupBox.addActionListener(new ActionHandler());
214            buddyAliasBox.addActionListener(new ActionHandler());
215            buddyGroups.addItemListener(
216                new ItemListener() {
217                    public void itemStateChanged(ItemEvent e) {
218                        String item = (String) e.getItem();
219                        if (item.equals(resources.getString("newGroup"))) {
220                            newGroupBox.setEnabled(true);
221                            newGroupBox.setText("");
222                            newGroupBox.grabFocus();
223                        } else {
224                            newGroupBox.setEnabled(false);
225                            if (newGroupBox.getText().equals("")) {
226                                newGroupBox.setText(resources.getString("newGroup"));
227                            }
228                        }
229                    }
230                });
231    
232            addWindowListener(
233                new WindowAdapter() {
234                    public void windowClosing(WindowEvent e) {
235                        cancelButtonHandler();
236                    }
237                });
238        }
239    
240    
241        /**
242         *  assures that all required information has been filled out in the dialog
243         *
244         *@return    Description of the Return Value
245         */
246        private boolean checkInformation() {
247            if (buddyIDBox.getText().equals("")) {
248                return Standard.warningMessage(this, resources.getString("addBuddyDialogTitle"), resources.getString("noIdError"));
249            }
250    
251            if (buddyAliasBox.getText().equals("")) {
252                return Standard.warningMessage(this, resources.getString("addBuddyDialogTitle"), resources.getString("noAliasError"));
253            }
254    
255            if (buddyGroups.getSelectedItem().equals(
256                    resources.getString("newGroup"))) {
257                if (newGroupBox.getText().equals("")
258                         || newGroupBox.getText().equals(
259                        resources.getString("newGroup"))) {
260                    return Standard.warningMessage(this, resources.getString("addBuddyDialogTitle"), resources.getString("newGroupError"));
261                }
262            }
263    
264            return true;
265        }
266    
267    
268        /**
269         *  Called by OK button - checks information and adds the buddy
270         */
271        private void okButtonHandler() {
272            if (checkInformation()) {
273                String buddyGroup = (String) buddyGroups.getSelectedItem();
274                if (buddyGroup.equals(resources.getString("newGroup"))) {
275                    buddyGroup = newGroupBox.getText();
276                }
277                if (buddyGroup.equals(resources.getString("none"))) {
278                    buddyGroup = null;
279                }
280    
281                addBuddy(buddyGroup, buddyAliasBox.getText(), buddyIDBox.getText());
282            }
283        }
284    
285    
286        /**
287         *  Handles all button events
288         *
289         *@author     Adam Olsen
290         *@created    September 26, 2005
291         *@version    1.0
292         */
293        class ActionHandler implements ActionListener {
294            /**
295             *  Description of the Method
296             *
297             *@param  e  Description of the Parameter
298             */
299            public void actionPerformed(ActionEvent e) {
300                if (e.getSource() != cancelButton) {
301                    okButtonHandler();
302                } else {
303                    cancelButtonHandler();
304                }
305            }
306        }
307    
308    
309        /**
310         *  Creates an input box with a corresponding label
311         *
312         *@param  container  the container to add the input box to
313         *@param  grid       the GridBagLayout to use
314         *@param  label      the label to use
315         *@param  box        the input box to use
316         */
317        private void createInputBox(Container container, GridBagLayout grid,
318                String label, Container box) {
319            JLabel labelBox = new JLabel(label + "    ");
320    
321            c.gridy = row++;
322            c.gridx = 0;
323            c.anchor = GridBagConstraints.EAST;
324            grid.setConstraints(labelBox, c);
325            container.add(labelBox);
326    
327            c.gridx = 1;
328            c.anchor = GridBagConstraints.WEST;
329            grid.setConstraints(box, c);
330            container.add(box);
331        }
332    
333    
334        /**
335         *  Gets the different available RosterGroups
336         *
337         *@return    an array of strings representing the RosterGroups
338         */
339        private String[] getRosterGroups() {
340            Roster roster = ConnectorThread.getInstance().getRoster();
341            String rosterGroups[] = new String[roster.getGroupCount() + 2];
342    
343            int i = 0;
344    
345            if ((!currentGroup.equals(""))) {
346                rosterGroups[i] = currentGroup;
347                i++;
348            }
349    
350            rosterGroups[i++] = resources.getString("none");
351            rosterGroups[i++] = resources.getString("newGroup");
352    
353            Iterator iterator = roster.getGroups();
354            while (iterator.hasNext()) {
355                RosterGroup rosterGroup = (RosterGroup) iterator.next();
356                if ((currentGroup.equals(""))
357                         || (!rosterGroup.getName().equals(currentGroup))) {
358                    rosterGroups[i] = rosterGroup.getName();
359                    i++;
360                }
361            }
362    
363            return rosterGroups;
364        }
365    
366    
367        /**
368         *  Runs the add buddy thread and adds or modifies a buddy in the Roster
369         *
370         *@param  groupName   the group to put the buddy in
371         *@param  buddyAlias  the alias of the buddy
372         *@param  buddyId     the buddy's JID
373         */
374        private void addBuddy(String groupName, String buddyAlias, String buddyId) {
375            Roster buddyGroups = ConnectorThread.getInstance()
376                    .getRoster();
377    
378            WaitDialog wait = new WaitDialog(this, null, resources.getString("pleaseWait"));
379            wait.setVisible(true);
380            setVisible(false);
381    
382            Thread thread = new Thread(new AddBuddyThread(wait, groupName,
383                    buddyAlias, buddyId, this));
384            thread.start();
385        }
386    
387    
388        /**
389         *  Actually adds the buddy to the Roster
390         *
391         *@author     Adam Olsen
392         *@created    September 26, 2005
393         *@version    1.0
394         */
395        class AddBuddyThread implements Runnable {
396            private String errorMessage;
397    
398            private String groupName;
399    
400            private String buddyAlias;
401    
402            private String buddyId;
403    
404            private AddBuddyDialog dialog;
405    
406            private WaitDialog wait;
407    
408    
409            /**
410             *  Default constructor
411             *
412             *@param  wait        the wait dialog
413             *@param  groupName   the group to use
414             *@param  buddyAlias  the buddy's alias
415             *@param  buddyId     the buddy's JID
416             *@param  dialog      the AddBuddyDialog that called this thread
417             */
418            public AddBuddyThread(WaitDialog wait, String groupName,
419                    String buddyAlias, String buddyId, AddBuddyDialog dialog) {
420                this.wait = wait;
421                this.groupName = groupName;
422                this.buddyAlias = buddyAlias;
423                this.buddyId = buddyId.trim();
424                this.dialog = dialog;
425            }
426    
427    
428            /**
429             *  Called by the enclosing Thread - will attempt to add the buddy to
430             *  the Roster, and will display an error if it wasn't successfull
431             */
432            public void run() {
433                final Roster roster = BuddyList.getInstance().getConnection().getRoster();
434                final BuddyStatus buddy = BuddyList.getInstance().getBuddyStatus(
435                        buddyId);
436                if (modify) {
437                    SwingUtilities.invokeLater(
438                        new Runnable() {
439                            public void run() {
440                                BuddyList.getInstance().getBuddyListTree().removeBuddy(
441                                        buddy, buddy.getGroup(), true);
442                            }
443                        });
444                }
445    
446                try {
447    
448    
449                    if (modify) {
450                        com.valhalla.Logger.debug("modifying roster item");
451                        RosterEntry entry = buddy.getRosterEntry();
452                        entry.setName(buddyAlias);
453                        int c = 0;
454                        Iterator groups = entry.getGroups();
455                        while (groups.hasNext()) {
456                            RosterGroup g = (RosterGroup) groups.next();
457                            if(!g.contains(entry)) continue;
458                            g.removeEntry(entry);
459                            c++;
460                        }
461    
462                        buddy.setTempGroup(groupName);
463                        SwingUtilities.invokeLater(new Runnable()
464                        {
465                            public void run()
466                            {
467                                dialog.setVisible(false);
468                                buddy.setRemoved(false);
469    
470                                NMOptionDialog.createMessageDialog(null, resources.getString("addBuddyDialogTitle"), resources.getString("buddyAdded"));
471    
472                                BuddyList.getInstance().getBuddyListTree().addBuddy(
473                                        buddy);
474                            }
475                        });
476    
477                        if (groupName != null && !groupName.equals("")) {
478                            RosterGroup newGroup = null;
479                            newGroup = roster.getGroup(groupName);
480                            if (newGroup == null) {
481                                com.valhalla.Logger.debug("had to create new group" + groupName);
482                                newGroup = roster.createGroup(groupName);
483                            } else {
484                                com.valhalla.Logger.debug("found group " + newGroup.getName());
485                            }
486    
487                            if (c != 0) {
488                                com.valhalla.Logger.debug("Moving buddy to " + newGroup.getName());
489                                newGroup.addEntry(entry);
490                            } else {
491                                roster.createEntry(buddyId, buddyAlias,
492                                        new String[]{groupName});
493    
494                            }
495                        }
496                    }
497                    /*
498                     *  if it's a new entry
499                     */else {
500    
501                        if (groupName == null) {
502                            roster.createEntry(buddyId, buddyAlias, null);
503                        } else {
504                            roster.createEntry(buddyId, buddyAlias,
505                                    new String[]{groupName});
506                            buddy.setTempGroup(groupName);
507                        }
508    
509                        SwingUtilities.invokeLater(new Runnable()
510                        {
511                            public void run()
512                            {
513                                dialog.setVisible(false);
514                                buddy.setRemoved(false);
515    
516                                NMOptionDialog.createMessageDialog(null, resources.getString("addBuddyDialogTitle"), resources.getString("buddyAdded"));
517    
518                                BuddyList.getInstance().getBuddyListTree().addBuddy(
519                                        buddy);
520                            }
521                        });
522                    }
523                } catch (XMPPException e) {
524                    if (e.getXMPPError() == null) {
525                        errorMessage = e.getMessage();
526                    } else {
527                        errorMessage = resources.getString("xmppError"
528                                 + e.getXMPPError().getCode());
529                    }
530                }
531    
532                SwingUtilities.invokeLater(
533                    new Runnable() {
534                        public void run() {
535                            wait.dispose();
536    
537                            if (errorMessage != null) {
538                                Standard.warningMessage(dialog, resources.getString("addBuddyDialogTitle"),
539                                        errorMessage);
540                                dialog.setVisible(true);
541                            } else {
542                                DialogTracker.removeDialog(dialog);
543    
544                            }
545                        }
546    
547                    });
548            }
549        }
550    }
551