001 package users.swing; 002 003 import javax.swing.*; 004 005 import java.util.*; 006 007 import users.*; 008 import users.events.*; 009 010 import util.*; 011 012 /** 013 * A ListModel modelling the set or a subset of users managed by a UserManager. 014 * 015 * @see UserManager 016 * @see User 017 * 018 * @author Steffen Zschaler 019 * @version 2.0 05/05/1999 020 * @since v2.0 021 */ 022 public class UserListModel extends AbstractListModel implements UserDataListener, HelpableListener { 023 024 /** 025 * A local copy of the list of users to provide easy and consistent access via an 026 * index. 027 * 028 * This model is kept up to date by registering as a listener with the UserManager. 029 * 030 * @serial 031 */ 032 protected List m_lUsers; 033 034 /** 035 * A Comparator that orders the users. By default, users are ordered by their name. 036 * 037 * @serial 038 */ 039 protected Comparator m_cmpComparator = new SerializableComparator() { 040 public int compare(Object o1, Object o2) { 041 return ((User)o1).getName().compareTo(((User)o2).getName()); 042 } 043 }; 044 045 /** 046 * A filter that defines the subset of users that are displayed. If <code>null</code> no 047 * filtering will occur. 048 * 049 * @serial 050 */ 051 protected UserFilter m_ufFilter; 052 053 /** 054 * The UserManager that is being modelled. 055 * 056 * @serial 057 */ 058 protected UserManager m_um; 059 060 /** 061 * Create a new UserListModel modelling the global UserManager. All Users will be displayed and they will be 062 * sorted by their names. 063 */ 064 public UserListModel() { 065 this(UserManager.getGlobalUM()); 066 } 067 068 /** 069 * Create a new UserListModel modelling the global UserManager. 070 * 071 * @param uf a filter that defines the set of users to be displayed. If <code>null</code>, no filtering will 072 * occur. 073 * @param cmp a Comparator that defines the order of the users to be displayed. The objects to be compared 074 * by this comparator will be Users. If <code>null</code>, users will be ordered by their names. 075 */ 076 public UserListModel(UserFilter uf, Comparator cmp) { 077 this(UserManager.getGlobalUM(), uf, cmp); 078 } 079 080 /** 081 * Create a new UserListModel modelling a given UserManager. All Users will be displayed and they will be 082 * sorted by their names. 083 * 084 * @param um the UserManager to be modelled. 085 */ 086 public UserListModel(UserManager um) { 087 this(um, null, null); 088 } 089 090 /** 091 * Create a new UserListModel modelling a given UserManager. 092 * 093 * @param um the UserManager to be modelled. 094 * @param uf a filter that defines the set of users to be displayed. If <code>null</code>, no filtering will 095 * occur. 096 * @param cmp a Comparator that defines the order of the users to be displayed. The objects to be compared 097 * by this comparator will be Users. If <code>null</code>, users will be ordered by their names. 098 */ 099 public UserListModel(UserManager um, UserFilter uf, Comparator cmp) { 100 super(); 101 102 // replace listener list for special support 103 listenerList = new ListenerHelper(this); 104 105 m_um = um; 106 m_ufFilter = uf; 107 108 if (cmp != null) { 109 m_cmpComparator = cmp; 110 } 111 112 updateModel(); 113 } 114 115 // List Model methods 116 117 /** 118 * Return the number of users in the model. 119 * 120 * @return the number of users in the model. 121 * 122 * @override Never 123 */ 124 public int getSize() { 125 // make sure internal model is up to date. 126 ((ListenerHelper)listenerList).needModelUpdate(); 127 128 return m_lUsers.size(); 129 } 130 131 /** 132 * Get a user by index. 133 * 134 * @param nIndex the index of the user to be returned. 135 * 136 * @return the user associated with the given index. 137 * 138 * @override Never 139 */ 140 public Object getElementAt(int nIndex) { 141 // make sure internal model is up to date. 142 ((ListenerHelper)listenerList).needModelUpdate(); 143 144 return m_lUsers.get(nIndex); 145 } 146 147 // UserDataListener methods 148 149 /** 150 * Respond to the <code>userAdded</code> event by updating the internal model 151 * and forwarding a translated version of the event to anyone who listens to us. 152 * 153 * @param e the event object describing the event. 154 * 155 * @override Sometimes 156 */ 157 public void userAdded(UserDataEvent e) { 158 updateModel(); 159 160 int nPos = m_lUsers.indexOf(e.getUser()); 161 162 if (nPos > -1) { 163 fireIntervalAdded(this, nPos, nPos); 164 } 165 } 166 167 /** 168 * Respond to the <code>userDeleted</code> event by updating the internal model 169 * and forwarding a translated version of the event to anyone who listens to us. 170 * 171 * @param e the event object describing the event. 172 * 173 * @override Sometimes 174 */ 175 public void userDeleted(UserDataEvent e) { 176 int nPos = m_lUsers.indexOf(e.getUser()); 177 178 updateModel(); 179 180 if (nPos > -1) { 181 fireIntervalRemoved(this, nPos, nPos); 182 } 183 } 184 185 // HelpableListener methods 186 /** 187 * Update the internal model. 188 * 189 * @override Sometimes 190 */ 191 public synchronized void updateModel() { 192 List lUsers = new LinkedList(m_um.getUsers()); 193 194 if (m_ufFilter != null) { 195 for (Iterator i = lUsers.iterator(); i.hasNext(); ) { 196 if (!m_ufFilter.match((User)i.next())) { 197 i.remove(); 198 } 199 } 200 } 201 202 Collections.sort(lUsers, m_cmpComparator); 203 204 m_lUsers = lUsers; 205 } 206 207 /** 208 * Subscribe to the UserManager to be informed of any changes in its set of users. 209 * 210 * @override Never 211 */ 212 public void subscribe() { 213 m_um.addUserDataListener(this); 214 } 215 216 /** 217 * Unsubscribe from the UserManager as there is no need to listen to it anymore, as 218 * we are not listened to anymore. From now on we are working in "poll-mode" until 219 * any listener indicates an interest in us again. 220 * 221 * @override Never 222 */ 223 public void unsubscribe() { 224 m_um.removeUserDataListener(this); 225 } 226 }