package esmska.data; import esmska.data.event.ActionEventSupport; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Collection; import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; import java.util.logging.Logger; /** Class managing all program contacts * @author ripper */ public class Contacts { /** new contact added */ public static final int ACTION_ADD_CONTACT = 0; /** existing contact removed */ public static final int ACTION_REMOVE_CONTACT = 1; /** all contacts removed */ public static final int ACTION_CLEAR_CONTACTS = 2; /** properties of some contact changed */ public static final int ACTION_CHANGE_CONTACT = 3; /** shared instance */ private static final Contacts instance = new Contacts(); private static final Logger logger = Logger.getLogger(Contacts.class.getName()); private final SortedSet<Contact> contacts = Collections.synchronizedSortedSet(new TreeSet<Contact>()); private ContactChangeListener contactChangeListener = new ContactChangeListener(); // <editor-fold defaultstate="collapsed" desc="ActionEvent support"> private ActionEventSupport actionSupport = new ActionEventSupport(this); public void addActionListener(ActionListener actionListener) { actionSupport.addActionListener(actionListener); } public void removeActionListener(ActionListener actionListener) { actionSupport.removeActionListener(actionListener); } // </editor-fold> /** Disabled contructor */ private Contacts() { } /** Get shared instance */ public static Contacts getInstance() { return instance; } /** Get unmodifiable collection of all contacts sorted by name */ public SortedSet<Contact> getAll() { return Collections.unmodifiableSortedSet(contacts); } /** Add new contact * @param contact new contact, not null * @return See {@link Collection#add} */ public boolean add(Contact contact) { if (contact == null) { throw new IllegalArgumentException("contact"); } logger.fine("Adding new contact: "+ contact); boolean added = false; synchronized(contacts) { added = contacts.add(contact); if (added) { contact.addPropertyChangeListener(contactChangeListener); } } if (added) { actionSupport.fireActionPerformed(ACTION_ADD_CONTACT, null); } return added; } /** Add new contacts * @param contacts collection of contacts, not null * @return See {@link Collection#addAll} */ public boolean addAll(Collection<Contact> contacts) { if (contacts == null) { throw new IllegalArgumentException("contacts"); } logger.fine("Adding " + contacts.size() + " contacts: " + contacts); boolean changed = false; synchronized(this.contacts) { for (Contact contact : contacts) { if (!this.contacts.contains(contact)) { contact.addPropertyChangeListener(contactChangeListener); } } changed = this.contacts.addAll(contacts); } if (changed) { actionSupport.fireActionPerformed(ACTION_ADD_CONTACT, null); } return changed; } /** Remove existing contact * @param contact contact to be removed, not null * @return See {@link Collection#remove} */ public boolean remove(Contact contact) { if (contact == null) { throw new IllegalArgumentException("contact"); } logger.fine("Removing contact: " + contact); boolean removed = false; synchronized(contacts) { removed = contacts.remove(contact); if (removed) { contact.removePropertyChangeListener(contactChangeListener); } } if (removed) { actionSupport.fireActionPerformed(ACTION_REMOVE_CONTACT, null); } return removed; } /** Remove existing contacts * @param contacts collection of contacts to be removed, not null * @return See {@link Collection#removeAll} */ public boolean removeAll(Collection<Contact> contacts) { if (contacts == null) { throw new IllegalArgumentException("contacts"); } logger.fine("Removing " + contacts.size() + " contacts: " + contacts); boolean changed = false; synchronized(this.contacts) { for (Contact contact : contacts) { if (this.contacts.contains(contact)) { contact.removePropertyChangeListener(contactChangeListener); } } changed = this.contacts.removeAll(contacts); } if (changed) { actionSupport.fireActionPerformed(ACTION_REMOVE_CONTACT, null); } return changed; } /** Remove all contacts */ public void clear() { logger.fine("Removing all contacts"); synchronized(contacts) { for (Contact contact : contacts) { contact.removePropertyChangeListener(contactChangeListener); } contacts.clear(); } actionSupport.fireActionPerformed(ACTION_CLEAR_CONTACTS, null); } /** Search for an existing contact * @param contact contact to be searched, not null * @return See {@link Collection#contains} */ public boolean contains(Contact contact) { if (contact == null) { throw new IllegalArgumentException("contact"); } return contacts.contains(contact); } /** Return number of contacts * @return See {@link Collection#size} */ public int size() { return contacts.size(); } /** Return if there are no contacts * @return See {@link Collection#isEmpty} */ public boolean isEmpty() { return contacts.isEmpty(); } /** Listener for changes in individual contacts notifying this class' * listeners that some contact's properties have changed. */ private class ContactChangeListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { actionSupport.fireActionPerformed(ACTION_CHANGE_CONTACT, null); } } }