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