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 }